Example usage for java.util.concurrent.locks ReadWriteLock writeLock

List of usage examples for java.util.concurrent.locks ReadWriteLock writeLock

Introduction

In this page you can find the example usage for java.util.concurrent.locks ReadWriteLock writeLock.

Prototype

Lock writeLock();

Source Link

Document

Returns the lock used for writing.

Usage

From source file:net.siegmar.japtproxy.misc.IOHandler.java

/**
 * This method is responsible for fetching remote data (if needed) and
 * sending the data (locally stored, or remotely fetched) to the client.
 *
 * @param requestedData  the requested data
 * @param poolObject     the pool object
 * @param targetResource the remote resource link
 * @param res            the HttpServletResponse object
 * @return true if the file was sent from cache, false otherwise
 * @throws IOException is thrown if a problem occured while sending data
 * @throws net.siegmar.japtproxy.exception.ResourceUnavailableException is thrown if the resource was not found
 *//*from   www  .  j a  v  a  2  s. c  o  m*/
public boolean sendAndSave(final RequestedData requestedData, final PoolObject poolObject,
        final URL targetResource, final HttpServletResponse res)
        throws IOException, ResourceUnavailableException, InitializationException {
    final String lockIdentifier = requestedData.getRequestedResource();
    final ReadWriteLock lock = ResourceLock.obtainLocker(lockIdentifier);
    final Lock readLock = lock.readLock();

    LockStatus lockStatus;

    readLock.lock();
    lockStatus = LockStatus.READ;

    LOG.debug("Obtained readLock for '{}'", lockIdentifier);

    final long poolModification = poolObject.getLastModified();

    FetchedResource fetchedResource = null;
    OutputStream saveOs = null;
    InputStream is = null;

    try {
        if (poolModification != 0) {
            if (!isNewVersionCheckRequired(poolObject, requestedData.getRequestedResource())) {
                LOG.debug("Local object exists and no need to do a version check - sending local object");
                sendLocalFile(poolObject, requestedData.getRequestModifiedSince(), res);
                return true;
            }

            LOG.debug("Local object exists but new version check is required");
        } else {
            LOG.debug("No local object exists - requesting remote host");
        }

        // Get a fetcher (http, ftp) for the current targetResource
        final Fetcher fetcher = fetcherPool.getInstance(targetResource);

        if (fetcher == null) {
            throw new InitializationException("No fetcher found for resource '" + targetResource + "'");
        }

        fetchedResource = fetcher.fetch(targetResource, poolModification, requestedData.getUserAgent());

        final String contentType = fetchedResource.getContentType();
        final long remoteModification = fetchedResource.getLastModified();
        final long contentLength = fetchedResource.getContentLength();

        if (remoteModification != 0 && poolModification > remoteModification) {
            LOG.warn(
                    "Remote object is older than local pool object "
                            + "(Remote timestamp: {} - Local timestamp: {}). "
                            + "Object won't get updated! Check this manually!",
                    Util.getSimpleDateFromTimestamp(remoteModification),
                    Util.getSimpleDateFromTimestamp(poolModification));
        }

        setHeader(res, fetchedResource);

        if (!fetchedResource.isModified()) {
            LOG.debug("Remote resource has no new version - sending local object");
            sendLocalFile(poolObject, requestedData.getRequestModifiedSince(), res);
            return true;
        }

        if (LOG.isDebugEnabled()) {
            if (poolModification != 0) {
                // Pool file exists, but it is out of date
                LOG.debug(
                        "Newer version found (old Last-Modified: {}) - Request '{}', Last-Modified: {}, "
                                + "Content-Type: {}, Content-Length: {}",
                        Util.getSimpleDateFromTimestamp(poolModification), targetResource,
                        Util.getSimpleDateFromTimestamp(remoteModification), contentType, contentLength);
            } else {
                // No pool file exists
                LOG.debug("Request '{}', Last-Modified: {}, Content-Type: {}, Content-Length: {}",
                        targetResource, Util.getSimpleDateFromTimestamp(remoteModification), contentType,
                        contentLength);
            }
        }

        readLock.unlock();
        lock.writeLock().lock();
        lockStatus = LockStatus.WRITE;

        LOG.debug("Obtained writeLock for '{}'", lockIdentifier);

        is = fetchedResource.getInputStream();

        LOG.info("Sending remote object '{}'", poolObject.getName());

        saveOs = new TeeOutputStream(poolObject.getOutputStream(), res.getOutputStream());
        final long bytesCopied = IOUtils.copyLarge(is, saveOs);

        LOG.debug("Data sent to file and client");

        poolObject.setLastModified(remoteModification);

        if (contentLength != -1 && bytesCopied != contentLength) {
            throw new IOException(
                    String.format("Received file has invalid file size - " + "only %d of %d were downloaded",
                            bytesCopied, contentLength));
        }

        poolObject.store();

        return false;
    } catch (final IOException e) {
        // Remove pool file if it was created by this thread
        if (poolModification == 0) {
            poolObject.remove();
        }

        throw e;
    } finally {
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(saveOs);

        if (fetchedResource != null) {
            fetchedResource.close();
        }

        if (lockStatus == LockStatus.WRITE) {
            LOG.debug("Released writeLock for '{}'", lockIdentifier);
            lock.writeLock().unlock();
        } else {
            LOG.debug("Released readLock for '{}'", lockIdentifier);
            readLock.unlock();
        }
        ResourceLock.releaseLocker(lockIdentifier);
    }
}