/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.rest;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.eclipse.skalli.commons.Statistics;
import org.eclipse.skalli.commons.UUIDUtils;
import org.eclipse.skalli.model.Project;
import org.eclipse.skalli.model.User;
import org.eclipse.skalli.services.Services;
import org.eclipse.skalli.services.entity.EntityServices;
import org.eclipse.skalli.services.permit.PermitService;
import org.eclipse.skalli.services.project.ProjectService;
import org.eclipse.skalli.services.user.UserServices;
import org.restlet.ext.servlet.ServerServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RestletServlet extends ServerServlet {
private static final long serialVersionUID = -7953560055729006206L;
private static final Logger LOG = LoggerFactory.getLogger(RestletServlet.class);
private static final String PROJECTS_PREFIX = "/projects/"; //$NON-NLS-1$
@Override
protected Class<?> loadClass(String className) throws ClassNotFoundException {
Class<?> ret = null;
// Try restlet classloader first
if (ret == null) {
try {
ret = super.loadClass(className);
} catch (ClassNotFoundException e) {
// Ignore, because that's the whole point here...
LOG.debug(MessageFormat.format("Class {0} not found in current bundle", className)); //$NON-NLS-1$
}
}
// Next, try the current context classloader
if (ret == null) {
try {
ret = Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
// Ignore, because that's the whole point here...
LOG.debug(MessageFormat.format("Class {0} not found by context class loader", className)); //$NON-NLS-1$
}
}
if (ret == null) {
throw new ClassNotFoundException("Class not found: " + className); //$NON-NLS-1$
}
return ret;
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
long timeBeginnProcessing = System.currentTimeMillis();
// extract the project from the request URL
Project project = getProject(request.getPathInfo());
// determine the user and login
PermitService permitService = Services.getRequiredService(PermitService.class);
String userId = permitService.login(request, project);
User user = null;
boolean isAnonymousUser = StringUtils.isBlank(userId);
if (!isAnonymousUser) {
user = UserServices.getUser(userId);
}
// track the request statistics
Statistics statistics = Statistics.getDefault();
if (user != null) {
statistics.trackUser(userId, user.getDepartment(), user.getLocation());
} else if (StringUtils.isNotBlank(userId)) {
statistics.trackUser(userId, null, null);
}
String referer = request.getHeader("Referer"); //$NON-NLS-1$
if (StringUtils.isBlank(referer)) {
referer = request.getParameter("referer"); //$NON-NLS-1$
}
if (StringUtils.isNotBlank(referer)) {
statistics.trackReferer(userId, referer);
}
String requestLine = MessageFormat.format("{0} {1}", //$NON-NLS-1$
request.getMethod(), request.getRequestURI());
if (project != null) {
requestLine = MessageFormat.format("{0} /api/projects/{1}", //$NON-NLS-1$
request.getMethod(), project.getProjectId());
}
statistics.trackUsage(userId, requestLine, referer);
String browser = request.getHeader("User-Agent"); //$NON-NLS-1$
if (StringUtils.isNotBlank(browser)) {
statistics.trackBrowser(userId, browser);
}
// perform the request
super.service(request, response);
// track the overall response time
long responseTime = System.currentTimeMillis() - timeBeginnProcessing;
statistics.trackResponseTime(userId, requestLine, responseTime);
LOG.info(MessageFormat.format("{0}: responseTime={1} milliseconds)", requestLine, Long.toString(responseTime)));
}
private Project getProject(String pathInfo) {
Project project = null;
if (StringUtils.isNotBlank(pathInfo) && pathInfo.startsWith(PROJECTS_PREFIX)) {
String projectId = getProjectId(pathInfo);
if (StringUtils.isNotBlank(projectId)) {
ProjectService projectService = ((ProjectService)EntityServices.getByEntityClass(Project.class));
project = projectService.getProjectByProjectId(projectId);
if (project == null && UUIDUtils.isUUID(projectId)) {
UUID uuid = UUIDUtils.asUUID(projectId);
project = projectService.getByUUID(uuid);
// project not found by UUID, search for deleted project by UUID
if (project == null) {
project = projectService.getDeletedProject(uuid);
}
}
}
}
return project;
}
private String getProjectId(String pathInfo) {
String s = pathInfo.substring(PROJECTS_PREFIX.length());
int posNextSlash = s.indexOf('/');
return posNextSlash > 0 ? s.substring(0, posNextSlash) : s;
}
}