Package com.ettrema.httpclient

Source Code of com.ettrema.httpclient.Host

package com.ettrema.httpclient;

import com.bradmcevoy.common.Path;
import com.bradmcevoy.http.Range;
import com.ettrema.cache.Cache;
import com.ettrema.cache.MemoryCache;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.OptionsMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* @author mcevoyb
*/
public class Host extends Folder {

  private static String PROPFIND_XML = "<?xml version=\"1.0\"?>"
      + "<d:propfind xmlns:d='DAV:' xmlns:c='clyde'><d:prop>"
      + "<d:resourcetype/><d:displayname/><d:getcontentlength/><d:creationdate/><d:getlastmodified/><d:iscollection/>"
      + "<d:quota-available-bytes/><d:quota-used-bytes/><c:crc/>"
      + "</d:prop></d:propfind>";
  private static final Logger log = LoggerFactory.getLogger(Host.class);
  public final String server;
  public final int port;
  public final String user;
  public final String password;
  public final String rootPath;
  /**
   * time in milliseconds to be used for all timeout parameters
   */
  private int timeout;
  final HttpClient client;
  public final List<ConnectionListener> connectionListeners = new ArrayList<ConnectionListener>();
  private String propFindXml = PROPFIND_XML;
//  private MetaFileMaker metaFileMaker = new MetaFileMaker();
//  private FileMaker fileMaker = new FileMaker();

  static {
//    System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
//    System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
//    System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire.header", "debug");
//    System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "debug");   
  }

  public Host(String server, int port, String user, String password, ProxyDetails proxyDetails) {
    this(server, null, port, user, password, proxyDetails, 30000, null);
  }

  public Host(String server, int port, String user, String password, ProxyDetails proxyDetails, Cache<Folder, List<Resource>> cache) {
    this(server, null, port, user, password, proxyDetails, 30000, cache); // defaul timeout of 30sec
  }

  public Host(String server, String rootPath, int port, String user, String password, ProxyDetails proxyDetails, Cache<Folder, List<Resource>> cache) {
    this(server, rootPath, port, user, password, proxyDetails, 30000, cache); // defaul timeout of 30sec
  }

  public Host(String server, String rootPath, int port, String user, String password, ProxyDetails proxyDetails, int timeout, Cache<Folder, List<Resource>> cache) {
    super((cache != null ? cache : new MemoryCache<Folder, List<Resource>>("resource-cache-default", 50, 20)));
    if (server == null) {
      throw new IllegalArgumentException("host name cannot be null");
    }
    this.rootPath = rootPath;
    this.timeout = timeout;
    this.server = server;
    this.port = port;
    this.user = user;
    this.password = password;
    client = new HttpClient();
    client.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
    if (user != null) {
      client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
    }

    if (user != null && user.length() > 0) {
      client.getParams().setAuthenticationPreemptive(true);
    }
    client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
    client.getParams().setSoTimeout(timeout);
    client.getParams().setConnectionManagerTimeout(timeout);
    if (proxyDetails != null) {
      if (proxyDetails.isUseSystemProxy()) {
        System.setProperty("java.net.useSystemProxies", "true");
      } else {
        System.setProperty("java.net.useSystemProxies", "false");
        if (proxyDetails.getProxyHost() != null && proxyDetails.getProxyHost().length() > 0) {
          HostConfiguration hostConfig = client.getHostConfiguration();
          hostConfig.setProxy(proxyDetails.getProxyHost(), proxyDetails.getProxyPort());
          if (proxyDetails.hasAuth()) {
            client.getState().setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyDetails.getUserName(), proxyDetails.getPassword()));
          }
        }
      }
    }
  }

  /**
   * Finds the resource by iterating through the path parts resolving collections
   * as it goes. If any path component is not founfd returns null
   *
   * @param path
   * @return
   * @throws IOException
   * @throws com.ettrema.httpclient.HttpException
   */
  public Resource find(String path) throws IOException, com.ettrema.httpclient.HttpException {
    return find(path, false);
  }
 
  public Resource find(String path, boolean invalidateCache) throws IOException, com.ettrema.httpclient.HttpException {
    if (path == null || path.length() == 0 || path.equals("/")) {
      return this;
    }
    if (path.startsWith("/")) {
      path = path.substring(1);
    }
    String[] arr = path.split("/");
    return _find(this, arr, 0, invalidateCache);   
  }
 

  public static Resource _find(Folder parent, String[] arr, int i, boolean invalidateCache) throws IOException, com.ettrema.httpclient.HttpException {
    String childName = arr[i];

    parent.flush();
    Resource child = parent.child(childName);
    if (i == arr.length - 1) {
      System.out.println("  child: " + child);
      return child;
    } else {
      if (child instanceof Folder) {       
        return _find((Folder) child, arr, i + 1, invalidateCache);
      } else {
        return null;
      }
    }
  }

  public Folder getFolder(String path) throws IOException, com.ettrema.httpclient.HttpException {
    Resource res = find(path);
    if (res instanceof Folder) {
      return (Folder) res;
    } else {
      throw new RuntimeException("Not a folder: " + res.href());
    }
  }

  synchronized PropFindMethod createPropFind(int depth, String href) {
    PropFindMethod m = new PropFindMethod(urlEncode(href));
    m.addRequestHeader(new Header("Depth", depth + ""));
    m.setDoAuthentication(true);
    return m;
  }

  public synchronized int doMkCol(String newUri) throws com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    MkColMethod p = new MkColMethod(urlEncode(newUri));
    try {
      int result = host().client.executeMethod(p);
      if (result == 409) {
        // probably means the folder already exists
        return result;
      }
      Utils.processResultCode(result, newUri);
      return result;
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    } finally {
      p.releaseConnection();
      notifyFinishRequest();
    }

  }

  public int doPut(Path path, InputStream content, Long contentLength, String contentType) {
    String dest = getHref(path);
    return doPut(dest, content, contentLength, contentType);
  }

  public synchronized int doPut(String newUri, InputStream content, Long contentLength, String contentType) {
    log.trace("put: " + newUri);
    notifyStartRequest();
    String s = urlEncode(newUri);
    PutMethod p = new PutMethod(s);

    HttpMethodParams params = new HttpMethodParams();
    params.setSoTimeout(timeout);
    p.setParams(params);
    try {
      RequestEntity requestEntity;
      if (contentLength == null) {
        log.trace("no content length");
        requestEntity = new InputStreamRequestEntity(content, contentType);
      } else {
        requestEntity = new InputStreamRequestEntity(content, contentLength, contentType);
      }
      p.setRequestEntity(requestEntity);
      int result = host().client.executeMethod(p);
      return result;
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    } finally {
      p.releaseConnection();
      notifyFinishRequest();
    }
  }

  public synchronized int doCopy(String from, String newUri) throws com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    CopyMethod m = new CopyMethod(urlEncode(from), urlEncode(newUri));
    try {
      int res = host().client.executeMethod(m);
      Utils.processResultCode(res, from);
      return res;
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    } finally {
      m.releaseConnection();
      notifyFinishRequest();
    }

  }

  public synchronized int doDelete(String href) throws IOException, com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    DeleteMethod m = new DeleteMethod(urlEncode(href));
    try {
      int res = host().client.executeMethod(m);
      Utils.processResultCode(res, href);
      return res;
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } finally {
      m.releaseConnection();
      notifyFinishRequest();
    }
  }

  public synchronized int doMove(String href, String newUri) throws IOException, com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    MoveMethod m = new MoveMethod(urlEncode(href), urlEncode(newUri));
    try {
      int res = host().client.executeMethod(m);
      Utils.processResultCode(res, href);
      return res;
    } finally {
      m.releaseConnection();
      notifyFinishRequest();
    }

  }

  public synchronized List<PropFindMethod.Response> doPropFind(String url, int depth) throws IOException, com.ettrema.httpclient.HttpException {
    log.trace("doPropFind: " + url);
    notifyStartRequest();
    PropFindMethod m = createPropFind(depth, url);

    try {
      if (propFindXml != null) {
        RequestEntity requestEntity = new StringRequestEntity(propFindXml, "text/xml", "UTF-8");
        m.setRequestEntity(requestEntity);
      }

      int res = client.executeMethod(m);
      Utils.processResultCode(res, url);
      if (res == 207) {
        return m.getResponses();
      } else {
        return null;
      }
    } catch (NotFoundException e) {
      log.trace("not found: " + url);
      return Collections.EMPTY_LIST;
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } finally {
      m.releaseConnection();
      notifyFinishRequest();
    }
  }

  /**
   *
   * @param url
   * @param receiver
   * @param rangeList - if null does a normal GET request
   * @throws com.ettrema.httpclient.HttpException
   * @throws com.ettrema.httpclient.Utils.CancelledException
   */
  public synchronized void doGet(String url, StreamReceiver receiver, List<Range> rangeList) throws com.ettrema.httpclient.HttpException, Utils.CancelledException {
    notifyStartRequest();
    HttpMethodBase m;
    if( rangeList != null ) {
      m = new RangedGetMethod(urlEncode(url), rangeList);
    } else {
      m = new GetMethod(urlEncode(url));
    }
    InputStream in = null;
    try {
      int res = client.executeMethod(m);
      Utils.processResultCode(res, url);
      in = m.getResponseBodyAsStream();
      receiver.receive(in);
    } catch (HttpException ex) {
      m.abort();
      throw new GenericHttpException(ex.getReasonCode(), url);
    } catch (Utils.CancelledException ex) {
      m.abort();
      throw ex;
    } catch (IOException ex) {
      m.abort();
      throw new RuntimeException(ex);
    } finally {
      Utils.close(in);
      m.releaseConnection();
      notifyFinishRequest();
    }
  }

  public synchronized void options(String path) throws java.net.ConnectException, Unauthorized, UnknownHostException, SocketTimeoutException, IOException, com.ettrema.httpclient.HttpException {
    String url = this.href() + path;
    doOptions(url);
  }

  public synchronized byte[] get(String path) throws com.ettrema.httpclient.HttpException, Utils.CancelledException {
    String url = this.href() + path;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    doGet(url, new StreamReceiver() {

      public void receive(InputStream in) {
        try {
          IOUtils.copy(in, out);
        } catch (IOException ex) {
          throw new RuntimeException(ex);
        }
      }
    }, null);
    return out.toByteArray();
  }

  private synchronized void doOptions(String url) throws NotFoundException, java.net.ConnectException, Unauthorized, java.net.UnknownHostException, SocketTimeoutException, IOException, com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    String uri = urlEncode(url);
    log.trace("doOptions: {}", url);
    OptionsMethod m = new OptionsMethod(uri);
    InputStream in = null;
    try {
      int res = client.executeMethod(m);
      log.trace("result code: " + res);
      if (res == 301 || res == 302) {
        return;
      }
      Utils.processResultCode(res, url);
    } finally {
      Utils.close(in);
      m.releaseConnection();
      notifyFinishRequest();
    }
  }

  /**
   * POSTs the variables and returns the body
   *
   * @param url
   * @param params
   * @return
   */
  public String doPost(String url, Map<String, String> params) throws com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    PostMethod m = new PostMethod(urlEncode(url));
    for (Entry<String, String> entry : params.entrySet()) {
      m.addParameter(entry.getKey(), entry.getValue());
    }
    InputStream in = null;
    try {
      int res = client.executeMethod(m);
      Utils.processResultCode(res, url);
      in = m.getResponseBodyAsStream();
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      IOUtils.copy(in, bout);
      return bout.toString();
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    } finally {
      Utils.close(in);
      m.releaseConnection();
      notifyFinishRequest();
    }
  }

  public String doPost(String url, Map<String, String> params, Part[] parts) throws com.ettrema.httpclient.HttpException {
    notifyStartRequest();
    PostMethod filePost = new PostMethod(urlEncode(url));
    if (params != null) {
      for (Entry<String, String> entry : params.entrySet()) {
        filePost.addParameter(entry.getKey(), entry.getValue());
      }
    }
    filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));

    InputStream in = null;
    try {
      int res = client.executeMethod(filePost);
      Utils.processResultCode(res, url);
      in = filePost.getResponseBodyAsStream();
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      IOUtils.copy(in, bout);
      return bout.toString();
    } catch (HttpException ex) {
      throw new RuntimeException(ex);
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    } finally {
      Utils.close(in);
      filePost.releaseConnection();
      notifyFinishRequest();
    }
  }

  @Override
  public Host host() {
    return this;
  }

  @Override
  public String href() {
    String s = "http://" + server;
    if (this.port != 80) {
      s += ":" + this.port;
    }
    s += "/";
    if (rootPath != null && rootPath.length() > 0) {
      if (!rootPath.equals("/")) {
        s = s + rootPath;
      }
    }
    if (!s.endsWith("/")) {
      s = s + "/";
    }
    //log.trace("host href: " + s);
    return s;
  }

  public String getHref(Path path) {
    String s = "http://" + server;
    if (this.port != 80) {
      s += ":" + this.port;
    }
    s += "/";
    if (rootPath != null && rootPath.length() > 0) {
      if (!rootPath.equals("/")) {
        s = s + rootPath;
      }
    }
    if (s.endsWith("/")) {
      if (!path.isRelative()) {
        s = s.substring(0, s.length() - 1);
      }
    } else {
      if (path.isRelative()) {
        s = s + "/";
      }
    }
    //log.trace("host href: " + s);
    return s + path; // path will be absolute
  }

  public static String urlEncode(String s) {
//        if( rootPath != null ) {
//            s = rootPath + s;
//        }
    return urlEncodePath(s);
  }

  public static String urlEncodePath(String s) {
    try {
      org.apache.commons.httpclient.URI uri = new URI(s, false);
      s = uri.toString();
      s = s.replace("&", "%26");
      return s;
    } catch (URIException ex) {
      throw new RuntimeException(s, ex);
    } catch (NullPointerException ex) {
      throw new RuntimeException(s, ex);
    }
    //s = s.replace( " ", "%20" );
  }

  void notifyStartRequest() {
    for (ConnectionListener l : connectionListeners) {
      l.onStartRequest();
    }
  }

  void notifyFinishRequest() {
    for (ConnectionListener l : connectionListeners) {
      l.onFinishRequest();
    }
  }

  public String getPropFindXml() {
    return propFindXml;
  }

  public void setPropFindXml(String propFindXml) {
    this.propFindXml = propFindXml;
  }

  public com.ettrema.httpclient.Folder getOrCreateFolder(Path remoteParentPath, boolean create) throws com.ettrema.httpclient.HttpException, IOException {
    log.trace("getOrCreateFolder: {}", remoteParentPath);
    com.ettrema.httpclient.Folder f = this;
    if (remoteParentPath != null) {
      for (String childName : remoteParentPath.getParts()) {
        if (childName.equals("_code")) {
          f = new Folder(f, childName, cache);
        } else {
          com.ettrema.httpclient.Resource child = f.child(childName);
          if (child == null) {
            if (create) {
              f = f.createFolder(childName);
            } else {
              return null;
            }
          } else if (child instanceof com.ettrema.httpclient.Folder) {
            f = (com.ettrema.httpclient.Folder) child;
          } else {
            log.warn("Can't upload. A resource exists with the same name as a folder, but is a file: " + remoteParentPath + " - " + child.getClass());
            return null;
          }
        }

      }
    }
    return f;
  }

  /**
   * @return the timeout
   */
  public int getTimeout() {
    return timeout;
  }

  /**
   * @param timeout the timeout to set
   */
  public void setTimeout(int timeout) {
    this.timeout = timeout;
  }
//
//  public java.io.File doSyncDownload(File remoteFile, java.io.File fLocalFile) throws com.ettrema.httpclient.HttpException, Exception {
//    final java.io.File fRemoteMeta = java.io.File.createTempFile("milton-zsync-remotemeta", null);
//    String url = remoteFile.href() + "/.zsync";
//    doGet(url, new StreamReceiver() {
//
//      @Override
//      public void receive(InputStream in) throws IOException {
//        FileOutputStream fout = new FileOutputStream(fRemoteMeta);
//        StreamUtils.readTo(in, fout, true, true);
//      }
//    }, null);   
//   
//    HttpRangeLoader rangeLoader = new HttpRangeLoader(remoteFile);
//    java.io.File mergedFile = fileMaker.make(fLocalFile, fRemoteMeta, rangeLoader);
//    return mergedFile;
//   
//  }
//
//  public void syncUpload(File aThis, java.io.File localFile) throws FileNotFoundException, com.ettrema.httpclient.HttpException, IOException {
//    int blockSize = metaFileMaker.computeBlockSize(localFile.length());
//    String url = aThis.href() + "/.zsync";   
//    java.io.File metaFile = metaFileMaker.make(url, blockSize, localFile);
//    Part[] parts = {new FilePart("meta", metaFile)};
//    String ranges = doPost(url, null, parts);
//    System.out.println("ranges: " + ranges);
//   
//    RangeListParser listParser = new RangeListParser();
//    List<Range> list = listParser.parse(new ByteArrayInputStream(ranges.getBytes()));
//   
//    LocalFileRangeLoader fileRangeLoader = new LocalFileRangeLoader(localFile);
//    byte[] data = fileRangeLoader.get(list);
//    System.out.println("sending bytes: " + data.length);
//    InputStream in = new ByteArrayInputStream(data);
//    int result = doPut(url, in, (long)data.length, null);
//    Utils.processResultCode(result, url );
//   
//  }
}
TOP

Related Classes of com.ettrema.httpclient.Host

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.