com.rexsl.page.BaseResource Maven / Gradle / Ivy
/**
* Copyright (c) 2011-2014, ReXSL.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met: 1) Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer. 2) Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution. 3) Neither the name of the ReXSL.com nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.rexsl.page;
import com.jcabi.aspects.Loggable;
import com.jcabi.log.Logger;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import lombok.ToString;
/**
* Base implementation of {@link Resource}.
*
* It is recommended to use this class as a base of all your JAX-RS resource
* classes and construct pages with {@link PageBuilder},
* on top of {@link BasePage}, for example:
*
*
@Path("/")
* public class MainRs extends BaseResource {
* @GET
* @Produces(MediaTypes.APPLICATION_XML)
* public BasePage front() {
* return new PageBuilder()
* .stylesheet("/xsl/front.xsl")
* .build(BasePage.class)
* .init(this)
* .append(new JaxbBundle("text", "Hello!"));
* }
* }
*
* The class is mutable and NOT thread-safe.
*
* @author Yegor Bugayenko ([email protected])
* @version $Id$
* @since 0.3.7
* @see BasePage
* @see PageBuilder
*/
@ToString
@Loggable(Loggable.DEBUG)
public class BaseResource implements Resource {
/**
* Start time of page building.
*/
private final transient long start = System.currentTimeMillis();
/**
* List of known JAX-RS providers, injected by JAX-RS implementation.
*/
private transient Providers iproviders;
/**
* URI info, injected by JAX-RS implementation.
*/
private transient UriInfo uri;
/**
* Http headers, injected by JAX-RS implementation.
*/
private final transient AtomicReference hdrs =
new AtomicReference();
/**
* HTTP servlet request, injected by JAX-RS implementation.
*/
private transient HttpServletRequest req;
/**
* Security context.
* @since 0.4.7
*/
private transient SecurityContext security;
/**
* Servlet context.
* @since 0.4.9
*/
private transient ServletContext ctx;
@Override
public final long started() {
return this.start;
}
@Override
@NotNull
public final Providers providers() {
this.assertNotNull(
this.iproviders,
"%[type]s#providers was never injected by JAX-RS"
);
return this.iproviders;
}
@Override
@NotNull
public final HttpHeaders httpHeaders() {
this.assertNotNull(
this.hdrs.get(),
"%[type]s#httpHeaders was never injected by JAX-RS"
);
return this.hdrs.get();
}
@Override
@NotNull
public final UriInfo uriInfo() {
this.assertNotNull(
this.uri,
"%[type]s#uriInfo was never injected by JAX-RS"
);
return this.uri;
}
@Override
@NotNull
public final HttpServletRequest httpServletRequest() {
this.assertNotNull(
this.req,
"%[type]s#httpRequest was never injected by JAX-RS"
);
return this.req;
}
/**
* {@inheritDoc}
* @since 0.4.7
*/
@Override
@NotNull
public final SecurityContext securityContext() {
this.assertNotNull(
this.security,
"%[type]s#securityContext was never injected by JAX-RS"
);
return this.security;
}
/**
* {@inheritDoc}
* @since 0.4.9
*/
@Override
@NotNull
public final ServletContext servletContext() {
this.assertNotNull(
this.ctx,
"%[type]s#servletContext was never injected by JAX-RS"
);
return this.ctx;
}
/**
* Set URI Info. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param info The info to inject
*/
@Context
public final void setUriInfo(@NotNull final UriInfo info) {
if (this.needsForwarding()) {
this.uri = new ForwardedUriInfo(info, this.hdrs);
} else {
this.uri = info;
}
}
/**
* Set Providers. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param prov List of providers
*/
@Context
public final void setProviders(@NotNull final Providers prov) {
this.iproviders = prov;
}
/**
* Set HttpHeaders. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param headers List of headers
*/
@Context
public final void setHttpHeaders(@NotNull final HttpHeaders headers) {
this.hdrs.set(headers);
}
/**
* Set HttpServletRequest. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param request The request
*/
@Context
public final void setHttpServletRequest(
@NotNull final HttpServletRequest request) {
this.req = request;
}
/**
* Set Security Context. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param context The security context
* @since 0.4.7
*/
@Context
public final void setSecurityContext(
@NotNull final SecurityContext context) {
this.security = context;
}
/**
* Set Servlet Context. Should be called by JAX-RS implementation
* because of {@code @Context} annotation.
* @param context The security context
* @since 0.4.9
*/
@Context
public final void setServletContext(
@NotNull final ServletContext context) {
this.ctx = context;
}
/**
* This resource needs forwarding of {@link UriInfo}?
* @return TRUE if yes, it needs to use {@link ForwardedUriInfo}
*/
private boolean needsForwarding() {
boolean needs = false;
Class> type = this.getClass();
while (type != null && !type.equals(Object.class)) {
if (type.isAnnotationPresent(Resource.Forwarded.class)) {
needs = true;
break;
}
type = type.getSuperclass();
}
return needs;
}
/**
* Asserts that an object is not null
and throws
* IllegalStateException if the object is null
.
* @param object The object to check
* @param message The exception message to use if the assertion fails
* @since 0.12
*/
private void assertNotNull(final Object object, final String message) {
if (object == null) {
throw new IllegalStateException(Logger.format(message, this));
}
}
}