1 /** 2 * Copyright (c) 2012-2017, s3auth.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the s3auth.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.s3auth.hosts; 31 32 import com.jcabi.aspects.Immutable; 33 import com.jcabi.aspects.Loggable; 34 import com.jcabi.immutable.Array; 35 import java.io.Closeable; 36 import java.io.IOException; 37 import java.io.OutputStream; 38 import java.net.HttpURLConnection; 39 import java.util.Collection; 40 import java.util.Date; 41 import javax.validation.constraints.NotNull; 42 import lombok.EqualsAndHashCode; 43 import lombok.ToString; 44 import org.apache.commons.codec.digest.DigestUtils; 45 import org.apache.commons.io.Charsets; 46 import org.apache.commons.io.IOUtils; 47 import org.apache.http.HttpHeaders; 48 49 /** 50 * Found resource. 51 * 52 * @author Yegor Bugayenko (yegor@tpc2.com) 53 * @version $Id: c31d6b662e1c3a6afeb91768a36717e936101741 $ 54 * @since 0.0.1 55 */ 56 @Immutable 57 @SuppressWarnings("PMD.TooManyMethods") 58 public interface Resource extends Closeable { 59 60 /** 61 * Get HTTP status. 62 * @return The status 63 */ 64 int status(); 65 66 /** 67 * Write its content to the writer. 68 * @param stream The stream to write to 69 * @return How many bytes were written 70 * @throws IOException If some error with I/O inside 71 */ 72 long writeTo(OutputStream stream) throws IOException; 73 74 /** 75 * Get a collection of all necessary HTTP headers for this resource. 76 * @return Collection of HTTP headers 77 * @throws IOException If some error with I/O inside 78 */ 79 Collection<String> headers() throws IOException; 80 81 /** 82 * Get its ETag. 83 * @return The etag 84 * @link <a href="http://en.wikipedia.org/wiki/HTTP_ETag">ETag</a> 85 */ 86 String etag(); 87 88 /** 89 * Get its last modified date. 90 * @return The last modified date. 91 */ 92 Date lastModified(); 93 94 /** 95 * Get the resource's HTTP Content-Type. 96 * @return The HTTP Content-Type of the resource. 97 */ 98 String contentType(); 99 100 /** 101 * Simple resource made out of plain text. 102 */ 103 @Immutable 104 @ToString 105 @EqualsAndHashCode(of = "text") 106 @Loggable(Loggable.DEBUG) 107 final class PlainText implements Resource { 108 /** 109 * Plain text to show. 110 */ 111 @Immutable.Array 112 private final transient byte[] text; 113 /** 114 * Last modified date to return. Equal to the time of object creation. 115 */ 116 private final transient long modified = System.currentTimeMillis(); 117 /** 118 * Headers associated with this resource. 119 */ 120 private final Array<String> hdrs; 121 /** 122 * Public ctor. 123 * @param txt The text to show 124 */ 125 public PlainText(@NotNull final String txt) { 126 this.text = txt.getBytes(Charsets.UTF_8); 127 this.hdrs = new Array<String>( 128 String.format( 129 "%s: %s", 130 HttpHeaders.CONTENT_TYPE, 131 this.contentType() 132 ), 133 String.format( 134 "%s: %d", 135 HttpHeaders.CONTENT_LENGTH, 136 this.text.length 137 ) 138 ); 139 } 140 @Override 141 public int status() { 142 return HttpURLConnection.HTTP_OK; 143 } 144 @Override 145 public long writeTo(@NotNull final OutputStream stream) 146 throws IOException { 147 IOUtils.write(this.text, stream); 148 return this.text.length; 149 } 150 @Override 151 public String etag() { 152 return DigestUtils.md5Hex(this.text); 153 } 154 @Override 155 public Date lastModified() { 156 return new Date(this.modified); 157 } 158 @Override 159 public String contentType() { 160 return "text/plain"; 161 } 162 @Override 163 @NotNull 164 public Collection<String> headers() { 165 return this.hdrs; 166 } 167 @Override 168 public void close() { 169 // nothing to do 170 } 171 } 172 173 }