001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.http.commons.domain; 019 020import org.glassfish.jersey.message.internal.HttpHeaderReader; 021 022import javax.servlet.http.HttpServletResponse; 023import java.text.ParseException; 024import java.util.HashMap; 025import java.util.Map; 026import java.util.Optional; 027 028/** 029 * Parse a single prefer tag, value and any optional parameters 030 * 031 * @author cabeer 032 */ 033public class PreferTag implements Comparable<PreferTag> { 034 private final String tag; 035 private String value = ""; 036 private Map<String, String> params = new HashMap<>(); 037 038 /** 039 * Create an empty PreferTag 040 * @return the empty PreferTag 041 */ 042 public static PreferTag emptyTag() { 043 return new PreferTag((String)null); 044 } 045 046 /** 047 * Create a new PreferTag from an existing tag 048 * @param preferTag the preferTag 049 */ 050 public PreferTag(final PreferTag preferTag) { 051 tag = preferTag.getTag(); 052 value = preferTag.getValue(); 053 params = preferTag.getParams(); 054 } 055 056 /** 057 * Parse the prefer tag and parameters out of the header 058 * @param reader the reader 059 */ 060 public PreferTag(final HttpHeaderReader reader) { 061 062 // Skip any white space 063 reader.hasNext(); 064 065 if (reader.hasNext()) { 066 try { 067 tag = Optional.ofNullable(reader.nextToken()) 068 .map(CharSequence::toString).orElse(null); 069 070 if (reader.hasNextSeparator('=', true)) { 071 reader.next(); 072 073 value = Optional.ofNullable(reader.nextTokenOrQuotedString()) 074 . map(CharSequence::toString) 075 .orElse(null); 076 } 077 078 if (reader.hasNext()) { 079 params = HttpHeaderReader.readParameters(reader); 080 if ( params == null ) { 081 params = new HashMap<>(); 082 } 083 } 084 } catch (ParseException e) { 085 throw new IllegalArgumentException("Could not parse 'Prefer' header", e); 086 } 087 } else { 088 tag = ""; 089 } 090 } 091 092 /** 093 * Create a blank prefer tag 094 * @param inputTag the input tag 095 */ 096 public PreferTag(final String inputTag) { 097 this(HttpHeaderReader.newInstance(inputTag)); 098 } 099 100 /** 101 * Get the tag name 102 * @return tag name 103 */ 104 public String getTag() { 105 return tag; 106 } 107 108 /** 109 * Get the default value for the tag 110 * @return default value for the tag 111 */ 112 public String getValue() { 113 return value; 114 } 115 116 /** 117 * Get any additional parameters for the prefer tag 118 * @return additional parameters for the prefer tag 119 */ 120 public Map<String,String> getParams() { 121 return params; 122 } 123 124 /** 125 * Add appropriate response headers to indicate that the incoming preferences were acknowledged 126 * @param servletResponse the servlet response 127 */ 128 public void addResponseHeaders(final HttpServletResponse servletResponse) { 129 if (!value.equals("minimal")) { 130 servletResponse.addHeader("Preference-Applied", "return=representation"); 131 } else { 132 servletResponse.addHeader("Preference-Applied", "return=minimal"); 133 } 134 servletResponse.addHeader("Vary", "Prefer"); 135 } 136 137 /** 138 * We consider tags with the same name to be equal, because <a 139 * href="http://tools.ietf.org/html/rfc7240#page-4">the definition of Prefer headers</a> does not permit that tags 140 * with the same name be consumed except by selecting for the first appearing tag. 141 * 142 * @see java.lang.Comparable#compareTo(java.lang.Object) 143 */ 144 @Override 145 public int compareTo(final PreferTag otherTag) { 146 return getTag().compareTo(otherTag.getTag()); 147 } 148 149 @Override 150 public boolean equals(final Object obj) { 151 if ((obj != null) && (obj instanceof PreferTag)) { 152 return getTag().equals(((PreferTag) obj).getTag()); 153 } 154 return false; 155 } 156 157 @Override 158 public int hashCode() { 159 if (getTag() == null) { 160 return 0; 161 } 162 return getTag().hashCode(); 163 } 164}