package act; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import act.app.ActionContext; import act.conf.AppConfig; import org.osgl.$; import org.osgl.http.H; import org.osgl.mvc.MvcConfig; import org.osgl.mvc.result.Ok; import org.osgl.mvc.result.Redirect; import org.osgl.storage.impl.SObject; import org.osgl.util.E; import org.osgl.util.IO; import java.io.File; import java.net.URL; import java.util.Locale; public abstract class ActResponse<T extends ActResponse> extends H.Response<T> { private boolean onResult; private boolean closed; protected String charset; protected Locale locale; protected String contentType; protected H.Format fmt; private boolean charsetSet; private boolean committed; protected int statusCode = -1; protected ActResponse() {} protected ActResponse(AppConfig config) { charset = config.encoding(); locale = config.locale(); } @Override public String characterEncoding() { return charset; } @Override public T characterEncoding(String encoding) { charset = encoding; charsetSet = true; return me(); } public T send(URL url) { String protocol = url.getProtocol(); if ("file".equals(protocol)) { return send(new File(url.getPath())); } writeBinary(SObject.of(IO.inputStream(url))); return me(); } public T send(File file) { writeBinary(SObject.of(file)); return me(); } @Override public T sendError(int sc, String msg) { throw E.unsupport(); } @Override public T sendError(int sc) { throw E.unsupport(); } @Override public T sendRedirect(String location) { throw new Redirect(location); } public T contentType(H.Format fmt) { contentType(fmt.contentType()); this.fmt = fmt; return me(); } public H.Format lastContentType() { return fmt; } /** * This response is ready for Result evaluation. */ public void onResult() { this.onResult = true; } public T commitContentType() { header(H.Header.Names.CONTENT_TYPE, _getContentType()); return me(); } @Override public void close() { super.close(); markClosed(); } public boolean isClosed() { return closed; } protected void markClosed() { this.closed = true; ActionContext ctx = context(); ctx.markAsReadyForClose(); } protected abstract void _setStatusCode(int sc); @Override public T status(int sc) { E.illegalArgumentIf(sc < 100, "Invalid status code"); statusCode = sc; _setStatusCode(sc); return me(); } @Override public int statusCode() { return statusCode; } public ActResponse beforeWritingContent() { if (onResult) { return this; } ActionContext ctx = context(); ctx.dissolve(); MvcConfig.applyBeforeCommitResultHandler(Ok.get(), ctx.req(), this); return this; } public ActResponse afterWritingContent() { if (committed) { return this; } commit(); ActionContext ctx = context(); MvcConfig.applyAfterCommitResultHandler(Ok.get(), ctx.req(), this); return this; } @Override public final void commit() { if (isCommitted()) { return; } committed = true; doCommit(); } protected abstract void doCommit(); protected final boolean isCommitted() { return committed; } @Override protected void _setContentType(String type) { this.contentType = type; } protected String _getContentType() { return this.contentType != null ? (this.charsetSet ? this.contentType + ";charset=" + this.charset : this.contentType) : null; } protected final T me() { return (T) this; } private ActionContext ctx() { return $.cast(this.context()); } }