• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aspectran / aspectran / #4053

10 Feb 2025 01:14PM CUT coverage: 35.271% (-0.02%) from 35.294%
#4053

push

github

topframe
Update

0 of 1 new or added line in 1 file covered. (0.0%)

155 existing lines in 3 files now uncovered.

14245 of 40387 relevant lines covered (35.27%)

0.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/web/src/main/java/com/aspectran/web/activity/response/AbstractRestResponse.java
1
/*
2
 * Copyright (c) 2008-2025 The Aspectran Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.aspectran.web.activity.response;
17

18
import com.aspectran.core.activity.Activity;
19
import com.aspectran.utils.Assert;
20
import com.aspectran.utils.FilenameUtils;
21
import com.aspectran.utils.LinkedCaseInsensitiveMultiValueMap;
22
import com.aspectran.utils.MultiValueMap;
23
import com.aspectran.utils.StringUtils;
24
import com.aspectran.utils.StringifyContext;
25
import com.aspectran.utils.annotation.jsr305.NonNull;
26
import com.aspectran.utils.annotation.jsr305.Nullable;
27
import com.aspectran.web.activity.request.RequestHeaderParser;
28
import com.aspectran.web.support.http.HttpHeaders;
29
import com.aspectran.web.support.http.HttpMediaTypeNotAcceptableException;
30
import com.aspectran.web.support.http.HttpStatus;
31
import com.aspectran.web.support.http.MediaType;
32

33
import java.nio.charset.Charset;
34
import java.util.List;
35
import java.util.Locale;
36

37
/**
38
 * Abstract class shared by RestResponse.
39
 *
40
 * <p>Created: 2019-06-16</p>
41
 */
42
public abstract class AbstractRestResponse implements RestResponse {
43

44
    private String name;
45

46
    private Object data;
47

48
    private StringifyContext stringifyContext;
49

UNCOV
50
    private boolean favorPathExtension = true;
×
51

UNCOV
52
    private boolean ignoreUnknownPathExtensions = true;
×
53

UNCOV
54
    private boolean ignoreAcceptHeader = false;
×
55

56
    private MediaType defaultContentType;
57

58
    private int status;
59

60
    private MultiValueMap<String, String> headers;
61

62
    public AbstractRestResponse() {
×
UNCOV
63
    }
×
64

65
    public AbstractRestResponse(Object data) {
66
        this(null, data);
×
UNCOV
67
    }
×
68

69
    public AbstractRestResponse(String name, Object data) {
×
70
        setData(name, data);
×
UNCOV
71
    }
×
72

73
    @Override
74
    public String getName() {
UNCOV
75
        return name;
×
76
    }
77

78
    @Override
79
    public Object getData() {
UNCOV
80
        return data;
×
81
    }
82

83
    @Override
84
    public boolean hasData() {
UNCOV
85
        return (data != null);
×
86
    }
87

88
    @Override
89
    public RestResponse setData(Object data) {
UNCOV
90
        return setData(null, data);
×
91
    }
92

93
    @Override
94
    public RestResponse setData(String name, Object data) {
95
        if (name != null) {
×
96
            name = name.trim();
×
97
            if (name.isEmpty()) {
×
UNCOV
98
                name = null;
×
99
            }
100
        }
101
        this.name = name;
×
102
        this.data = data;
×
UNCOV
103
        return this;
×
104
    }
105

106
    @Override
107
    @Nullable
108
    public StringifyContext getStringifyContext() {
UNCOV
109
        return stringifyContext;
×
110
    }
111

112
    @Override
113
    @NonNull
114
    public StringifyContext touchStringifyContext() {
UNCOV
115
        if (stringifyContext == null) {
×
116
            stringifyContext = new StringifyContext();
×
117
        }
UNCOV
118
        return stringifyContext;
×
119
    }
120

121
    @Override
122
    public void setStringifyContext(StringifyContext stringifyContext) {
UNCOV
123
        this.stringifyContext = stringifyContext;
×
UNCOV
124
    }
×
125

126
    @Override
127
    public RestResponse stringifyContext(StringifyContext stringifyContext) {
UNCOV
128
        setStringifyContext(stringifyContext);
×
UNCOV
129
        return this;
×
130
    }
131

132
    @Override
133
    public RestResponse nullWritable(boolean nullWritable) {
UNCOV
134
        touchStringifyContext().setNullWritable(nullWritable);
×
UNCOV
135
        return this;
×
136
    }
137

138
    @Override
139
    public boolean isFavorPathExtension() {
UNCOV
140
        return favorPathExtension;
×
141
    }
142

143
    @Override
144
    public void setFavorPathExtension(boolean favorPathExtension) {
UNCOV
145
        this.favorPathExtension = favorPathExtension;
×
UNCOV
146
    }
×
147

148
    @Override
149
    public RestResponse favorPathExtension(boolean favorPathExtension) {
UNCOV
150
        setFavorPathExtension(favorPathExtension);
×
UNCOV
151
        return this;
×
152
    }
153

154
    @Override
155
    public boolean isIgnoreUnknownPathExtensions() {
UNCOV
156
        return ignoreUnknownPathExtensions;
×
157
    }
158

159
    @Override
160
    public void setIgnoreUnknownPathExtensions(boolean ignoreUnknownPathExtensions) {
UNCOV
161
        this.ignoreUnknownPathExtensions = ignoreUnknownPathExtensions;
×
UNCOV
162
    }
×
163

164
    @Override
165
    public RestResponse ignoreUnknownPathExtensions(boolean ignoreUnknownPathExtensions) {
UNCOV
166
        setIgnoreUnknownPathExtensions(ignoreUnknownPathExtensions);
×
UNCOV
167
        return this;
×
168
    }
169

170
    @Override
171
    public boolean isIgnoreAcceptHeader() {
UNCOV
172
        return ignoreAcceptHeader;
×
173
    }
174

175
    @Override
176
    public void setIgnoreAcceptHeader(boolean ignoreAcceptHeader) {
UNCOV
177
        this.ignoreAcceptHeader = ignoreAcceptHeader;
×
UNCOV
178
    }
×
179

180
    @Override
181
    public RestResponse ignoreAcceptHeader(boolean ignoreAcceptHeader) {
UNCOV
182
        setIgnoreAcceptHeader(ignoreAcceptHeader);
×
UNCOV
183
        return this;
×
184
    }
185

186
    @Override
187
    public MediaType getDefaultContentType() {
UNCOV
188
        return defaultContentType;
×
189
    }
190

191
    @Override
192
    public void setDefaultContentType(MediaType defaultContentType) {
UNCOV
193
        this.defaultContentType = defaultContentType;
×
UNCOV
194
    }
×
195

196
    @Override
197
    public void setDefaultContentType(String defaultContentType) {
UNCOV
198
        this.defaultContentType = MediaType.parseMediaType(defaultContentType);
×
UNCOV
199
    }
×
200

201
    @Override
202
    public RestResponse defaultContentType(MediaType defaultContentType) {
UNCOV
203
        setDefaultContentType(defaultContentType);
×
UNCOV
204
        return this;
×
205
    }
206

207
    @Override
208
    public RestResponse ok() {
209
        this.status = HttpStatus.OK.value();
×
UNCOV
210
        return this;
×
211
    }
212

213
    @Override
214
    public RestResponse created() {
215
        return created(null);
×
216
    }
217

218
    @Override
219
    public RestResponse created(String location) {
220
        this.status = HttpStatus.CREATED.value();
×
221
        setHeader(HttpHeaders.LOCATION, location);
×
UNCOV
222
        return this;
×
223
    }
224

225
    @Override
226
    public RestResponse accepted() {
227
        this.status = HttpStatus.ACCEPTED.value();
×
UNCOV
228
        return this;
×
229
    }
230

231
    @Override
232
    public RestResponse noContent() {
233
        this.status = HttpStatus.NO_CONTENT.value();
×
UNCOV
234
        return this;
×
235
    }
236

237
    @Override
238
    public RestResponse movedPermanently() {
239
        this.status = HttpStatus.MOVED_PERMANENTLY.value();
×
UNCOV
240
        return this;
×
241
    }
242

243
    @Override
244
    public RestResponse seeOther() {
245
        this.status = HttpStatus.SEE_OTHER.value();
×
UNCOV
246
        return this;
×
247
    }
248

249
    @Override
250
    public RestResponse notModified() {
251
        this.status = HttpStatus.NOT_MODIFIED.value();
×
UNCOV
252
        return this;
×
253
    }
254

255
    @Override
256
    public RestResponse temporaryRedirect() {
257
        this.status = HttpStatus.TEMPORARY_REDIRECT.value();
×
UNCOV
258
        return this;
×
259
    }
260

261
    @Override
262
    public RestResponse badRequest() {
263
        this.status = HttpStatus.BAD_REQUEST.value();
×
UNCOV
264
        return this;
×
265
    }
266

267
    @Override
268
    public RestResponse unauthorized() {
269
        this.status = HttpStatus.UNAUTHORIZED.value();
×
UNCOV
270
        return this;
×
271
    }
272

273
    @Override
274
    public RestResponse forbidden() {
275
        this.status = HttpStatus.FORBIDDEN.value();
×
UNCOV
276
        return this;
×
277
    }
278

279
    @Override
280
    public RestResponse notFound() {
281
        this.status = HttpStatus.NOT_FOUND.value();
×
UNCOV
282
        return this;
×
283
    }
284

285
    @Override
286
    public RestResponse methodNotAllowed() {
287
        this.status = HttpStatus.METHOD_NOT_ALLOWED.value();
×
UNCOV
288
        return this;
×
289
    }
290

291
    @Override
292
    public RestResponse notAcceptable() {
293
        this.status = HttpStatus.NOT_ACCEPTABLE.value();
×
UNCOV
294
        return this;
×
295
    }
296

297
    @Override
298
    public RestResponse conflict() {
299
        this.status = HttpStatus.CONFLICT.value();
×
UNCOV
300
        return this;
×
301
    }
302

303
    @Override
304
    public RestResponse preconditionFailed() {
305
        this.status = HttpStatus.PRECONDITION_FAILED.value();
×
UNCOV
306
        return this;
×
307
    }
308

309
    @Override
310
    public RestResponse unsupportedMediaType() {
UNCOV
311
        this.status = HttpStatus.UNSUPPORTED_MEDIA_TYPE.value();
×
UNCOV
312
        return this;
×
313
    }
314

315
    @Override
316
    public RestResponse internalServerError() {
UNCOV
317
        this.status = HttpStatus.INTERNAL_SERVER_ERROR.value();
×
UNCOV
318
        return this;
×
319
    }
320

321
    @Override
322
    public int getStatus() {
323
        return status;
×
324
    }
325

326
    @Override
327
    public RestResponse setStatus(int status) {
328
        this.status = status;
×
329
        return this;
×
330
    }
331

332
    @Override
333
    public RestResponse setStatus(HttpStatus status) {
UNCOV
334
        Assert.notNull(status, "'status' must not be null");
×
UNCOV
335
        this.status = status.value();
×
UNCOV
336
        return this;
×
337
    }
338

339
    @Override
340
    public RestResponse setHeader(String name, String value) {
341
        if (name == null) {
×
UNCOV
342
            throw new IllegalArgumentException("Header name must not be null");
×
343
        }
UNCOV
344
        touchHeaders().set(name, value);
×
345
        return this;
×
346
    }
347

348
    @Override
349
    public RestResponse addHeader(String name, String value) {
350
        if (name == null) {
×
UNCOV
351
            throw new IllegalArgumentException("Header name must not be null");
×
352
        }
UNCOV
353
        touchHeaders().add(name, value);
×
UNCOV
354
        return this;
×
355
    }
356

357
    protected MultiValueMap<String, String> getHeaders() {
UNCOV
358
        return headers;
×
359
    }
360

361
    private MultiValueMap<String, String> touchHeaders() {
362
        if (headers == null) {
×
363
            headers = new LinkedCaseInsensitiveMultiValueMap<>();
×
364
        }
365
        return headers;
×
366
    }
367

368
    protected abstract List<MediaType> getSupportedContentTypes();
369

370
    protected abstract MediaType getContentTypeByPathExtension(String extension);
371

372
    protected MediaType determineAcceptContentType(@NonNull Activity activity)
373
            throws HttpMediaTypeNotAcceptableException {
UNCOV
374
        if (isFavorPathExtension()) {
×
375
            String path = activity.getTranslet().getRequestName();
×
376
            String ext = FilenameUtils.getExtension(path);
×
377
            if (StringUtils.hasLength(ext)) {
×
378
                ext = ext.toLowerCase(Locale.ENGLISH);
×
379
                MediaType contentType = getContentTypeByPathExtension(ext);
×
380
                if (contentType != null) {
×
381
                    return contentType;
×
382
                }
383
            }
384
            if (!isIgnoreUnknownPathExtensions()) {
×
385
                throw new HttpMediaTypeNotAcceptableException(getSupportedContentTypes());
×
386
            }
387
        }
388
        if (!isIgnoreAcceptHeader()) {
×
389
            List<MediaType> acceptContentTypes = RequestHeaderParser.resolveAcceptContentTypes(activity.getRequestAdapter());
×
390
            for (MediaType contentType : acceptContentTypes) {
×
UNCOV
391
                if (contentType.equalsTypeAndSubtype(MediaType.ALL) &&
×
UNCOV
392
                        getDefaultContentType() != null &&
×
393
                        getSupportedContentTypes().contains(getDefaultContentType())) {
×
UNCOV
394
                    return getDefaultContentType();
×
395
                }
UNCOV
396
                for (MediaType supportedContentType : getSupportedContentTypes()) {
×
397
                    if (contentType.includes(supportedContentType)) {
×
398
                        return contentType;
×
399
                    }
400
                }
×
401
            }
×
UNCOV
402
            if (getSupportedContentTypes().contains(getDefaultContentType())) {
×
UNCOV
403
                return getDefaultContentType();
×
404
            }
405
        }
UNCOV
406
        throw new HttpMediaTypeNotAcceptableException(getSupportedContentTypes());
×
407
    }
408

409
    protected MediaType determineResponseContentType(@NonNull Activity activity, @NonNull MediaType acceptContentType) {
UNCOV
410
        Charset charset = acceptContentType.getCharset();
×
UNCOV
411
        if (charset == null) {
×
412
            String encoding = determineIntendedEncoding(activity);
×
UNCOV
413
            if (encoding != null) {
×
UNCOV
414
                charset = Charset.forName(encoding);
×
415
            }
416
        }
UNCOV
417
        if (charset != null) {
×
UNCOV
418
            return new MediaType(acceptContentType.getType(), acceptContentType.getSubtype(), charset);
×
419
        } else {
UNCOV
420
            return new MediaType(acceptContentType.getType(), acceptContentType.getSubtype());
×
421
        }
422
    }
423

424
    protected String determineIntendedEncoding(@NonNull Activity activity) {
UNCOV
425
        return activity.getTranslet().getDefinitiveResponseEncoding();
×
426
    }
427

428
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc