org.bibalex.gallery.storage.BAGStorage.java Source code

Java tutorial

Introduction

Here is the source code for org.bibalex.gallery.storage.BAGStorage.java

Source

//   Copyright 2013 Bibliotheca Alexandrina, Wellcome Trust Library
//
//   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.bibalex.gallery.storage;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.vfs.AllFileSelector;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.VFS;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import org.bibalex.gallery.exception.BAGException;
import org.bibalex.util.URLPathStrUtils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

import edu.emory.mathcs.backport.java.util.Collections;

public abstract class BAGStorage {

    private static final int DEFAULT_CONN_TIMEOUT = 10000;

    public static URL cacheFileLocally(String cacheLocalPath, String fileUrlStr) throws BAGException {
        try {
            // String extension = "";
            //
            // int lastDotIx = fileUrlStr.lastIndexOf('.');
            // if (lastDotIx > fileUrlStr.lastIndexOf('/')) {
            // extension = fileUrlStr.substring(lastDotIx);
            // }
            // String cacheFileName = "cached" + fileUrlStr.hashCode() + extension;

            int lastSlashIx = fileUrlStr.lastIndexOf('/');

            String cacheFileName = fileUrlStr.substring(lastSlashIx + 1);

            String cacheFilePath = URLPathStrUtils.appendParts(cacheLocalPath, cacheFileName);

            FileSystemManager fsMgr = VFS.getManager();

            final FileObject cacheFileFO = fsMgr.resolveFile(cacheFilePath);
            final FileObject cacheDirFO = fsMgr.resolveFile(cacheLocalPath);

            if (!cacheFileFO.exists()) {
                synchronized (BAGStorage.class) {

                    if (!cacheDirFO.exists()) {
                        cacheDirFO.createFolder();
                    }

                    cacheFileFO.createFile();

                    OutputStream cacheFileOut = cacheFileFO.getContent().getOutputStream();
                    try {
                        readRemoteFile(fileUrlStr, cacheFileOut);
                    } finally {
                        cacheFileOut.close();
                    }

                }
            }

            return cacheFileFO.getURL();

        } catch (FileSystemException e) {
            throw new BAGException(e);
        } catch (IOException e) {
            throw new BAGException(e);
        }
    }

    public static void copyFile(String sourceUrlStr, String targetUrlsStr) throws BAGException {
        try {
            FileObject targetFO = VFS.getManager().resolveFile(targetUrlsStr);
            FileObject sourceFO = VFS.getManager().resolveFile(sourceUrlStr);

            targetFO.copyFrom(sourceFO, new AllFileSelector());
        } catch (FileSystemException e) {
            throw new BAGException(e);
        }
    }

    public static List<String> listChildren(String dirUrlStr, FileType childrenType) throws BAGException {
        return listChildren(dirUrlStr, childrenType, DEFAULT_CONN_TIMEOUT);
    }

    public static List<String> listChildren(String dirUrlStr, FileType childrenType, int timeout)
            throws BAGException {

        try {
            List<String> result;

            if (new URI(dirUrlStr).getScheme().startsWith("http")) {
                BasicHttpParams httpParams = new BasicHttpParams();

                HttpConnectionParams.setConnectionTimeout(httpParams, timeout);

                DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
                try {
                    result = listChildrenApacheHttpd(dirUrlStr, childrenType, httpClient);

                } finally {
                    // When HttpClient instance is no longer needed,
                    // shut down the connection manager to ensure
                    // immediate deallocation of all system resources
                    httpClient.getConnectionManager().shutdown();
                }
            } else {

                result = new ArrayList<String>();

                FileSystemManager fsMgr = VFS.getManager();

                FileObject dir = fsMgr.resolveFile(dirUrlStr);

                final FileObject[] children = dir.getChildren();

                for (final FileObject child : children) {
                    if ((childrenType == FileType.FILE_OR_FOLDER) || (child.getType() == childrenType)) {
                        result.add(child.getName().getBaseName());
                    }
                }
            }
            // TODO define a comparator that orders the files properly as in
            // http://forums.sun.com/thread.jspa?threadID=5289401
            Collections.sort(result);

            return result;

        } catch (FileSystemException e) {
            throw new BAGException(e);
        } catch (URISyntaxException e) {
            throw new BAGException(e);
        }
    }

    protected static List<String> listChildrenApacheHttpd(String dirUrlStr, FileType childrenType,
            DefaultHttpClient httpclient) throws BAGException {
        ArrayList<String> result = new ArrayList<String>();

        HttpGet httpReq = new HttpGet(dirUrlStr);
        try {

            HttpResponse response = httpclient.execute(httpReq);

            if (response.getStatusLine().getStatusCode() / 100 != 2) {
                throw new BAGException("Connection error: " + response.getStatusLine().toString());
            }

            // Get hold of the response entity
            HttpEntity entity = response.getEntity();

            // If the response does not enclose an entity, there is no need
            // to bother about connection release
            if ((entity != null)) {

                entity = new BufferedHttpEntity(entity);

                if (entity.getContentType().getValue().startsWith("text/html")) {
                    SAXBuilder saxBuilder = new SAXBuilder();

                    saxBuilder.setFeature("http://xml.org/sax/features/validation", false);
                    saxBuilder.setFeature("http://xml.org/sax/features/namespaces", true);
                    saxBuilder.setFeature("http://xml.org/sax/features/namespace-prefixes", true);

                    String htmlresponse = EntityUtils.toString(entity);
                    String xmlResponse = light_html2xml.Html2Xml(htmlresponse);

                    Document doc = saxBuilder.build(new StringReader(xmlResponse));
                    XPath hrefXP = XPath.newInstance("//a/@href");

                    for (Object obj : hrefXP.selectNodes(doc)) {
                        Attribute attr = (Attribute) obj;
                        String name = attr.getValue();
                        if (name.startsWith("/")) {
                            // parent dir
                            continue;
                        } else if (name.endsWith("/")) {
                            if (childrenType.equals(FileType.FOLDER)
                                    || childrenType.equals(FileType.FILE_OR_FOLDER)) {
                                result.add(name.substring(0, name.length() - 1));
                            }
                        } else {
                            if (childrenType.equals(FileType.FILE)
                                    || childrenType.equals(FileType.FILE_OR_FOLDER)) {
                                result.add(name);
                            }
                        }
                    }
                }
            }

            return result;

        } catch (IOException ex) {

            // In case of an IOException the connection will be released
            // back to the connection manager automatically
            throw new BAGException(ex);

        } catch (RuntimeException ex) {

            // In case of an unexpected exception you may want to abort
            // the HTTP request in order to shut down the underlying
            // connection and release it back to the connection manager.
            httpReq.abort();
            throw ex;

        } catch (JDOMException e) {
            throw new BAGException(e);
        } finally {
            // connection closing is left for the caller to reuse connections

        }

    }

    public static InputStream openFileForInput(String fileUrlStr) throws BAGException {
        try {
            FileObject FO = VFS.getManager().resolveFile(fileUrlStr);
            return FO.getContent().getInputStream();
        } catch (FileSystemException e) {
            throw new BAGException(e);
        }

    }

    public static OutputStream openFileForOutput(String fileUrlStr, boolean bAppend) throws BAGException {
        try {
            FileSystemManager mgr = VFS.getManager();

            FileObject fileFO = mgr.resolveFile(fileUrlStr);

            return fileFO.getContent().getOutputStream(bAppend);

        } catch (FileSystemException e) {
            throw new BAGException(e);
        }
    }

    public static boolean putFile(String remoteUrlStr, File localFile, String contentType) throws BAGException {
        return putFile(remoteUrlStr, localFile, contentType, DEFAULT_CONN_TIMEOUT);
    }

    public static boolean putFile(String remoteUrlStr, File localFile, String contentType, int timeout)
            throws BAGException {
        HttpPut httpput = null;
        DefaultHttpClient httpclient = null;
        try {
            BasicHttpParams httpParams = new BasicHttpParams();

            HttpConnectionParams.setConnectionTimeout(httpParams, timeout);

            httpclient = new DefaultHttpClient(httpParams);
            URI remoteUrl = new URI(remoteUrlStr);
            String userInfo = remoteUrl.getUserInfo();
            if ((userInfo != null) && !userInfo.isEmpty()) {
                int colonIx = userInfo.indexOf(':');
                httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(remoteUrl.getHost(), remoteUrl.getPort()), new UsernamePasswordCredentials(
                                userInfo.substring(0, colonIx), userInfo.substring(colonIx + 1)));
            }

            if ((contentType == null) || contentType.isEmpty()) {
                contentType = "text/plain; charset=\"UTF-8\"";
            }

            FileEntity entity = new FileEntity(localFile, contentType);

            httpput = new HttpPut(remoteUrlStr);
            httpput.setEntity(entity);

            HttpResponse response = httpclient.execute(httpput);
            return response.getStatusLine().getStatusCode() - 200 < 100;

        } catch (IOException ex) {

            // In case of an IOException the connection will be released
            // back to the connection manager automatically
            throw new BAGException(ex);

        } catch (RuntimeException ex) {

            // In case of an unexpected exception you may want to abort
            // the HTTP request in order to shut down the underlying
            // connection and release it back to the connection manager.
            httpput.abort();
            throw ex;

        } catch (URISyntaxException e) {
            // will be still null: httpput.abort();
            throw new BAGException(e);
        } finally {

            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();

        }
    }

    public static void readRemoteFile(String fileUrlStr, OutputStream localOut) throws BAGException {
        try {
            try {
                FileObject imageFO;

                imageFO = VFS.getManager().resolveFile(fileUrlStr);

                InputStream imageIS = imageFO.getContent().getInputStream();

                byte buffer[] = new byte[10240];
                int bytesRead = 0;
                do {
                    bytesRead = imageIS.read(buffer);

                    if (bytesRead > 0) {
                        localOut.write(buffer, 0, bytesRead);
                    } else {
                        break;
                    }
                } while (true);

            } finally {
                localOut.flush();
            }

        } catch (FileSystemException e) {
            throw new BAGException(e);
        } catch (IOException e) {
            throw new BAGException(e);

        }
    }

}