Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put duplicated methods into a common superclass #5537

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -67,7 +67,7 @@
*
* @author Marek Potociar
*/
public abstract class InboundMessageContext {
public abstract class InboundMessageContext extends MessageHeaderMethods {

private static final InputStream EMPTY = new InputStream() {

Expand Down Expand Up @@ -100,7 +100,6 @@ public boolean markSupported() {
private final boolean translateNce;
private MessageBodyWorkers workers;
private final Configuration configuration;
private final RuntimeDelegate runtimeDelegateDecorator;
private LazyValue<MediaType> contentTypeCache;
private LazyValue<List<AcceptableMediaType>> acceptTypeCache;

Expand Down Expand Up @@ -166,11 +165,11 @@ public InboundMessageContext(Configuration configuration) {
* as required by JAX-RS specification on the server side.
*/
public InboundMessageContext(Configuration configuration, boolean translateNce) {
super(configuration);
this.headers = new GuardianStringKeyMultivaluedMap<>(HeaderUtils.createInbound());
this.entityContent = new EntityContent();
this.translateNce = translateNce;
this.configuration = configuration;
runtimeDelegateDecorator = RuntimeDelegateDecorator.configured(configuration);

contentTypeCache = contentTypeCache();
acceptTypeCache = acceptTypeCache();
Expand Down Expand Up @@ -319,42 +318,9 @@ public String getHeaderString(String name) {
return buffer.toString();
}

/**
* Get a single typed header value.
*
* @param name header name.
* @param converter from string conversion function. Is expected to throw {@link ProcessingException}
* if conversion fails.
* @param convertNull if {@code true} this method calls the provided converter even for {@code null}. Otherwise this
* method returns the {@code null} without calling the converter.
* @return value of the header, or (possibly converted) {@code null} if not present.
*/
private <T> T singleHeader(String name, Function<String, T> converter, boolean convertNull) {
final List<String> values = this.headers.get(name);

if (values == null || values.isEmpty()) {
return convertNull ? converter.apply(null) : null;
}
if (values.size() > 1) {
throw new HeaderValueException(LocalizationMessages.TOO_MANY_HEADER_VALUES(name, values.toString()),
HeaderValueException.Context.INBOUND);
}

Object value = values.get(0);
if (value == null) {
return convertNull ? converter.apply(null) : null;
}

try {
return converter.apply(HeaderUtils.asString(value, runtimeDelegateDecorator));
} catch (ProcessingException ex) {
throw exception(name, value, ex);
}
}

private static HeaderValueException exception(final String headerName, Object headerValue, Exception e) {
return new HeaderValueException(LocalizationMessages.UNABLE_TO_PARSE_HEADER_VALUE(headerName, headerValue), e,
HeaderValueException.Context.INBOUND);
@Override
public HeaderValueException.Context getHeaderValueExceptionContext() {
return HeaderValueException.Context.INBOUND;
}

/**
Expand All @@ -366,24 +332,6 @@ public MultivaluedMap<String, String> getHeaders() {
return this.headers;
}

/**
* Get message date.
*
* @return the message date, otherwise {@code null} if not present.
*/
public Date getDate() {
return singleHeader(HttpHeaders.DATE, new Function<String, Date>() {
@Override
public Date apply(String input) {
try {
return HttpHeaderReader.readDate(input);
} catch (ParseException ex) {
throw new ProcessingException(ex);
}
}
}, false);
}

/**
* Get If-Match header.
*
Expand Down Expand Up @@ -418,42 +366,6 @@ public Set<MatchingEntityTag> getIfNoneMatch() {
}
}

/**
* Get the language of the entity.
*
* @return the language of the entity or {@code null} if not specified.
*/
public Locale getLanguage() {
return singleHeader(HttpHeaders.CONTENT_LANGUAGE, new Function<String, Locale>() {
@Override
public Locale apply(String input) {
try {
return new LanguageTag(input).getAsLocale();
} catch (ParseException e) {
throw new ProcessingException(e);
}
}
}, false);
}

/**
* Get Content-Length value.
*
* @return Content-Length as integer if present and valid number. In other cases returns -1.
*/
public int getLength() {
return singleHeader(HttpHeaders.CONTENT_LENGTH, new Function<String, Integer>() {
@Override
public Integer apply(String input) {
try {
return (input != null && !input.isEmpty()) ? Integer.parseInt(input) : -1;
} catch (NumberFormatException ex) {
throw new ProcessingException(ex);
}
}
}, true);
}

/**
* Get the media type of the entity.
*
Expand Down Expand Up @@ -568,120 +480,6 @@ public List<AcceptableToken> getQualifiedAcceptEncoding() {
}
}

/**
* Get any cookies that accompanied the request.
*
* @return a read-only map of cookie name (String) to {@link javax.ws.rs.core.Cookie}.
*/
public Map<String, Cookie> getRequestCookies() {
List<String> cookies = this.headers.get(HttpHeaders.COOKIE);
if (cookies == null || cookies.isEmpty()) {
return Collections.emptyMap();
}

Map<String, Cookie> result = new HashMap<String, Cookie>();
for (String cookie : cookies) {
if (cookie != null) {
result.putAll(HttpHeaderReader.readCookies(cookie));
}
}
return result;
}

/**
* Get the allowed HTTP methods from the Allow HTTP header.
*
* @return the allowed HTTP methods, all methods will returned as upper case
* strings.
*/
public Set<String> getAllowedMethods() {
final String allowed = getHeaderString(HttpHeaders.ALLOW);
if (allowed == null || allowed.isEmpty()) {
return Collections.emptySet();
}
try {
return new HashSet<String>(HttpHeaderReader.readStringList(allowed.toUpperCase(Locale.ROOT)));
} catch (java.text.ParseException e) {
throw exception(HttpHeaders.ALLOW, allowed, e);
}
}

/**
* Get any new cookies set on the response message.
*
* @return a read-only map of cookie name (String) to a {@link javax.ws.rs.core.NewCookie new cookie}.
*/
public Map<String, NewCookie> getResponseCookies() {
List<String> cookies = this.headers.get(HttpHeaders.SET_COOKIE);
if (cookies == null || cookies.isEmpty()) {
return Collections.emptyMap();
}

Map<String, NewCookie> result = new HashMap<String, NewCookie>();
for (String cookie : cookies) {
if (cookie != null) {
NewCookie newCookie = HttpHeaderReader.readNewCookie(cookie);
String cookieName = newCookie.getName();
if (result.containsKey(cookieName)) {
result.put(cookieName, HeaderUtils.getPreferredCookie(result.get(cookieName), newCookie));
} else {
result.put(cookieName, newCookie);
}
}
}
return result;
}

/**
* Get the entity tag.
*
* @return the entity tag, otherwise {@code null} if not present.
*/
public EntityTag getEntityTag() {
return singleHeader(HttpHeaders.ETAG, new Function<String, EntityTag>() {
@Override
public EntityTag apply(String value) {
return EntityTag.valueOf(value);
}
}, false);
}

/**
* Get the last modified date.
*
* @return the last modified date, otherwise {@code null} if not present.
*/
public Date getLastModified() {
return singleHeader(HttpHeaders.LAST_MODIFIED, new Function<String, Date>() {
@Override
public Date apply(String input) {
try {
return HttpHeaderReader.readDate(input);
} catch (ParseException e) {
throw new ProcessingException(e);
}
}
}, false);
}

/**
* Get the location.
*
* @return the location URI, otherwise {@code null} if not present.
*/
public URI getLocation() {
return singleHeader(HttpHeaders.LOCATION, new Function<String, URI>() {
@Override
public URI apply(String value) {
try {
return URI.create(value);
} catch (IllegalArgumentException ex) {
throw new ProcessingException(ex);
}
}
}, false);
}

/**
* Get the links attached to the message as header.
*
Expand Down Expand Up @@ -726,57 +524,6 @@ public Set<Link> getLinks() {
}
}

/**
* Check if link for relation exists.
*
* @param relation link relation.
* @return {@code true} if the for the relation link exists, {@code false}
* otherwise.
*/
public boolean hasLink(String relation) {
for (Link link : getLinks()) {
List<String> relations = LinkProvider.getLinkRelations(link.getRel());

if (relations != null && relations.contains(relation)) {
return true;
}
}
return false;
}

/**
* Get the link for the relation.
*
* @param relation link relation.
* @return the link for the relation, otherwise {@code null} if not present.
*/
public Link getLink(String relation) {
for (Link link : getLinks()) {
List<String> relations = LinkProvider.getLinkRelations(link.getRel());
if (relations != null && relations.contains(relation)) {
return link;
}
}
return null;
}

/**
* Convenience method that returns a {@link javax.ws.rs.core.Link.Builder Link.Builder}
* for the relation.
*
* @param relation link relation.
* @return the link builder for the relation, otherwise {@code null} if not
* present.
*/
public Link.Builder getLinkBuilder(String relation) {
Link link = getLink(relation);
if (link == null) {
return null;
}

return Link.fromLink(link);
}

// Message entity

/**
Expand Down
Loading
Loading