org.rhq.enterprise.server.rest.ReportsInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.enterprise.server.rest.ReportsInterceptor.java

Source

/*
 *
 *  * RHQ Management Platform
 *  * Copyright (C) 2005-2012 Red Hat, Inc.
 *  * All rights reserved.
 *  *
 *  * This program is free software; you can redistribute it and/or modify
 *  * it under the terms of the GNU General Public License as published by
 *  * the Free Software Foundation version 2 of the License.
 *  *
 *  * This program is distributed in the hope that it will be useful,
 *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  * GNU General Public License for more details.
 *  *
 *  * You should have received a copy of the GNU General Public License
 *  * along with this program; if not, write to the Free Software
 *  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

package org.rhq.enterprise.server.rest;

import java.io.IOException;
import java.io.OutputStream;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.naming.OperationNotSupportedException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.server.auth.SessionException;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;

/**
 * @author John Sanda
 */
public class ReportsInterceptor {

    private final Log log = LogFactory.getLog(ReportsInterceptor.class);

    @Resource
    private EJBContext ejbContext;

    @EJB
    private SubjectManagerLocal subjectManager;

    @AroundInvoke
    public Object setCaller(final InvocationContext ctx) throws Exception {
        AbstractRestBean target = (AbstractRestBean) ctx.getTarget();

        boolean fromRest = false;
        // If we are "forwarded" from the "normal" rest-api, we have a principal, that we can use
        java.security.Principal p = ejbContext.getCallerPrincipal();
        if (p != null) {
            target.caller = subjectManager.getSubjectByName(p.getName());
            fromRest = true;
        }

        // If no caller was set from the "normal" api, we need to check if it is
        // available in cookies, as in this case we were invoked
        // from the Coregui reports function
        if (target.caller == null) {
            HttpServletRequest request = getRequest(ctx.getParameters());
            if (request == null) {
                // TODO should we throw a different exception?
                String msg = "No " + HttpServletRequest.class.getName() + " parameter was found for "
                        + getMethodName(ctx) + ". An " + HttpServletRequest.class.getName()
                        + " parameter must be specified in order to support authentication";
                log.error(msg);
                throw new OperationNotSupportedException(msg);
            }

            Subject subject = getSubject(request);
            if (subject == null) {
                throw new IllegalAccessException(
                        "Failed to validate request: could not access subject for request URL "
                                + request.getRequestURL());
            }

            target.caller = subject;
        }

        // Invoke the target method
        Object result = ctx.proceed();

        if (result instanceof StreamingOutput) {
            return new LoggingStreamingOutput((StreamingOutput) result, getMethodName(ctx));
        }

        // TODO invalidate session?

        return result;
    }

    private String getMethodName(InvocationContext ctx) {
        return ctx.getTarget().getClass().getName() + "." + ctx.getMethod().getName();
    }

    private HttpServletRequest getRequest(Object[] params) {
        for (Object param : params) {
            if (param instanceof HttpServletRequest) {
                return (HttpServletRequest) param;
            }
        }
        return null;
    }

    private Subject getSubject(HttpServletRequest request) {
        Cookie rhqSession = getCookie(request, "RHQ_Session");
        if (rhqSession == null) {
            return null;
        }
        String sessionId = rhqSession.getValue();

        SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
        try {
            return subjectMgr.getSubjectBySessionId(Integer.parseInt(sessionId));
        } catch (NumberFormatException e) {
            log.warn(sessionId + " is not a valid session id.", e);
            return null;
        } catch (SessionException e) {
            log.warn("Could not get subject for session id " + sessionId, e);
            return null;
        } catch (Exception e) {
            log.error("An unexpected exception occurred while trying to access subject for session id " + sessionId,
                    e);
            return null;
        }
    }

    private Cookie getCookie(HttpServletRequest request, String name) {
        if (request.getCookies() == null)
            return null;

        for (Cookie cookie : request.getCookies()) {
            if (cookie.getName().equals(name)) {
                return cookie;
            }
        }
        return null;
    }

    private class LoggingStreamingOutput implements StreamingOutput {

        String methodName;
        StreamingOutput delegate;

        public LoggingStreamingOutput(StreamingOutput delegate, String methodName) {
            this.delegate = delegate;
            this.methodName = methodName;
        }

        @Override
        public void write(OutputStream output) throws IOException, WebApplicationException {
            long start = System.currentTimeMillis();
            try {
                delegate.write(output);
            } catch (IOException e) {
                log.error("An exception occurred while executing " + methodName, e);
                throw e;
            } catch (RuntimeException e) {
                log.error("An exception occurred while executing " + methodName, e);
                throw e;
            }
            long end = System.currentTimeMillis();
            if (log.isDebugEnabled()) {
                log.debug(methodName + " finished streaming report in " + (end - start) + " ms");
            }
        }
    }
}