/** * Copyright (C) 2012-2014 Gist Labs, LLC. (http://gistlabs.com) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.gistlabs.mechanize; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.Collection; import java.util.Collections; import org.apache.http.Header; import org.apache.http.HttpMessage; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpRequestBase; import com.gistlabs.mechanize.exceptions.MechanizeException; import com.gistlabs.mechanize.exceptions.MechanizeExceptionFactory; import com.gistlabs.mechanize.requestor.RequestBuilder; import com.gistlabs.mechanize.requestor.RequestBuilderFactory; import com.gistlabs.mechanize.util.NullOutputStream; import com.gistlabs.mechanize.util.Util; import com.gistlabs.mechanize.util.apache.ContentType; /** * Represents a resource being reseived by a request. * * @author Martin Kersten<Martin.Kersten.mk@gmail.com> */ public abstract class AbstractResource implements RequestBuilderFactory<Resource>, Resource { @SuppressWarnings("unchecked") public static Collection<String> CONTENT_MATCHERS = Collections.EMPTY_LIST; private final Mechanize agent; private final String uri; private final HttpRequestBase request; protected final HttpResponse response; public AbstractResource(final Mechanize agent, final HttpRequestBase request, final HttpResponse response) { this.agent = agent; this.request = request; this.response = response; this.uri = inspectUri(request, response); try { loadPage(); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw MechanizeExceptionFactory.newException(e); } } protected void loadPage() throws Exception { preLoadContent(); } protected void preLoadContent() throws IOException { Util.copy(getInputStream(), new NullOutputStream()); } protected String getContentEncoding(final HttpResponse response) { try { ContentType contentType = ContentType.get(response.getEntity()); return contentType.getCharset().displayName(); } catch (NullPointerException np) { // TODO why don't test cases set this? return null; } } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getInputStream() */ @Override public InputStream getInputStream() throws IOException { return this.response.getEntity().getContent(); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getLength() */ @Override public long getLength() { return this.response.getEntity().getContentLength(); } protected int getIntContentLength(final HttpResponse response) { long longLength = response.getEntity().getContentLength(); if (longLength<0) return 0; else if (longLength>Integer.MAX_VALUE) return Integer.MAX_VALUE; else return (int)longLength; } protected String inspectUri(final HttpRequestBase request, final HttpResponse response) { Header contentLocation = Util.findHeader(response, "content-location"); if (contentLocation != null && contentLocation.getValue() != null) return contentLocation.getValue(); Header mechanizeLocation = Util.findHeader(response, Mechanize.MECHANIZE_LOCATION); if (mechanizeLocation!=null && mechanizeLocation.getValue()!=null) return mechanizeLocation.getValue(); return request.getURI().toString(); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getContentType() */ @Override public String getContentType() { return response.getEntity().getContentType().getValue(); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#doRequest(java.lang.String) */ @Override public RequestBuilder<Resource> doRequest(final String uri) { return getAgent().doRequest(uri); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getTitle() */ @Override public String getTitle() { return ""; } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getUri() */ @Override public String getUri() { return uri; } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#size() */ @Override public long size() { return this.response.getEntity().getContentLength(); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getRequest() */ @Override public HttpRequestBase getRequest() { return request; } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getResponse() */ @Override public HttpResponse getResponse() { return response; } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#getAgent() */ @Override public Mechanize getAgent() { return agent; } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#asString() */ @Override public String asString() { ByteArrayOutputStream result = new ByteArrayOutputStream(getIntContentLength(this.response)); saveTo(result); return result.toString(); } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#saveTo(java.io.File) */ @Override public void saveTo(final File file) { if(file.exists()) throw new IllegalArgumentException("File '" + file.toString() + "' already exists."); try { saveTo(new FileOutputStream(file)); } catch (FileNotFoundException e) { throw MechanizeExceptionFactory.newException(e); } } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#saveTo(java.io.OutputStream) */ @Override public void saveTo(final OutputStream out) { try { Util.copy(getInputStream(), out); } catch (IOException e) { throw new MechanizeException(e); } } /* (non-Javadoc) * @see com.gistlabs.mechanize.Resource#saveToString() */ @Override public String saveToString() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); saveTo(baos); return new String(baos.toByteArray()); } @Override public String absoluteUrl(final String uri) { try { URL baseUrl = new URL(getUri()); return new URL(baseUrl, uri).toExternalForm(); } catch (MalformedURLException e) { throw MechanizeExceptionFactory.newException(e); } } @Override public String toString() { StringWriter result = new StringWriter(); PrintWriter writer = new PrintWriter(result); writer.println("== Request =="); writer.println(getRequest().getRequestLine().toString()); write(getRequest(), writer); writer.println(); writer.println("== Response =="); writer.println(getResponse().getStatusLine().toString()); write(getResponse(), writer); return result.toString(); } private void write(final HttpMessage message, final PrintWriter writer) { Header[] headers = message.getAllHeaders(); for (Header header : headers) writer.println(header.toString()); } }