/* $HeadURL:: $
* $Id$
*
* Copyright (c) 2009-2010 DuraSpace
* http://duraspace.org
*
* In collaboration with Topaz Inc.
* http://www.topazproject.org
*
* 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 org.akubraproject.www;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.akubraproject.Blob;
import org.akubraproject.BlobStoreConnection;
import org.akubraproject.DuplicateBlobException;
import org.akubraproject.MissingBlobException;
import org.akubraproject.impl.AbstractBlob;
import org.akubraproject.impl.StreamManager;
/**
* A WWW resource as a Blob.
*
* @author Pradeep Krishnan
*/
class WWWBlob extends AbstractBlob {
private static final Logger logger = LoggerFactory.getLogger(WWWBlob.class);
private final URL url;
private final StreamManager streamManager;
private Long size;
private Boolean exists;
private URLConnection urlc;
private InputStream content;
/**
* Creates a new WWWBlob object.
*
* @param url the www url
* @param conn the connection object
* @param streamManager the stream-manager
*/
public WWWBlob(URL url, BlobStoreConnection conn, StreamManager streamManager) {
super(conn, toURI(url));
this.url = url;
this.streamManager = streamManager;
}
private static URI toURI(URL url) {
try {
return url.toURI();
} catch (URISyntaxException e) {
throw new Error("unexpected exception", e);
}
}
/**
* Notification that the BlobStoreConnection is closed.
*/
void closed() {
urlc = null;
exists = null;
size = null;
if (content != null) {
try {
content.close();
} catch (IOException ioe) {
logger.warn("Error closing input-stream for '" + id + "'", ioe);
}
}
}
private URLConnection connect(boolean input, boolean cache) throws IOException {
ensureOpen();
URLConnection con;
if ((urlc != null) && input)
con = urlc;
else {
con = url.openConnection();
con.setAllowUserInteraction(false);
if (input)
con.setDoInput(true);
else
con.setDoOutput(true);
}
if (input) {
try {
content = streamManager.manageInputStream(owner, con.getInputStream());
exists = true;
} catch (FileNotFoundException fnfe) {
logger.debug("blob doesn't exist for '" + id + "'", fnfe);
exists = false;
size = null;
urlc = null;
throw new MissingBlobException(id);
}
size = (long) con.getContentLength();
/*
* close() on the InputStream will disconnect.
* So the connection should not be cached in that case.
* For getSize(), the caching the connection is a valid option.
*/
urlc = cache ? con : null;
}
return con;
}
@Override
public long getSize() throws IOException {
if (exists != null && !exists)
throw new MissingBlobException(id);
if (size == null)
connect(true, true);
return size;
}
@Override
public InputStream openInputStream() throws IOException {
connect(true, false);
return content;
}
@Override
public OutputStream openOutputStream(long estimatedSize, boolean overwrite) throws IOException {
if (!overwrite && exists())
throw new DuplicateBlobException(id);
URLConnection con = connect(false, false);
OutputStream os = streamManager.manageOutputStream(owner, con.getOutputStream());
exists = true;
return os;
}
@Override
public boolean exists() throws IOException {
if (exists == null) {
try {
connect(true, true);
} catch (MissingBlobException mbe) {
logger.trace("blob doesn't exist for '" + id + "'", mbe);
return false;
}
}
return exists;
}
@Override
public void delete() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Blob moveTo(URI blobId, Map<String, String> hints) throws IOException {
throw new UnsupportedOperationException();
}
}