/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Astroboa 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.console.security; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URLDecoder; import java.util.Enumeration; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.ws.rs.ApplicationPath; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.CmsRepository; import org.betaconceptframework.astroboa.context.AstroboaClientContextHolder; import org.betaconceptframework.astroboa.context.SecurityContext; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.util.Base64; import org.jboss.resteasy.util.GenericType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Resource locator representing the main entry of all * requests for one or more resources from a Astroboa repository. * * This class is responsible to login to the provided repository id * and then to forward request to the appropriate sub resource. * * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ @ApplicationPath("/") @Path("/") public class ResourceApiProxy { private final Logger logger = LoggerFactory.getLogger(getClass()); @GET @PUT @POST @DELETE @Path("{resourceApiPath:.*}") @Produces("*/*") public Response dispatchToAstroboaRepository( @PathParam("resourceApiPath") String resourceApiPath, @Context UriInfo uriInfo, @Context HttpServletRequest httpServletRequest){ try { String repositoryId = AstroboaClientContextHolder.getActiveRepositoryId(); if (StringUtils.isBlank(repositoryId)) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } CmsRepository activeCmsRepository = AstroboaClientContextHolder.getActiveCmsRepository(); if (activeCmsRepository == null) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } SecurityContext securityContext = AstroboaClientContextHolder.getActiveSecurityContext(); if (securityContext == null) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } String username = securityContext.getIdentity(); if (StringUtils.isBlank(username)) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } String resourceApiBasePath = activeCmsRepository.getRestfulApiBasePath(); if (StringUtils.isBlank(resourceApiBasePath)) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } HttpSession httpSession = httpServletRequest.getSession(); String password = (String) httpSession.getAttribute("repositoryPassword"); if (StringUtils.isBlank(password)) { throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND); } String httpMethod = httpServletRequest.getMethod(); String requestPath = uriInfo.getPath(); MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters(); ClientRequest request = new ClientRequest("http://localhost:8080" + resourceApiBasePath + "/" + repositoryId + requestPath); // read the payload if the http method is put or post if (httpMethod.equals("POST") || httpMethod.equals("PUT")) { request.body(httpServletRequest.getContentType(), getBody(httpServletRequest)); } // add authorization header (BASIC AUTH) String basicAuthString = username + ":" + password; String authorization = "BASIC "+ Base64.encodeBytes(basicAuthString.getBytes()); request.header(HttpHeaders.AUTHORIZATION, authorization); // add headers Enumeration headerNames = httpServletRequest.getHeaderNames(); while(headerNames.hasMoreElements()) { String headerName = (String)headerNames.nextElement(); request.header(headerName, httpServletRequest.getHeader(headerName)); } // add query parameters for (Map.Entry queryParamEntry : queryParameters.entrySet()) { String parameterValue = ((List<String>)queryParamEntry.getValue()).get(0); //ClientRequest (request) encodes the values before the execution of the request. //Therefore we need to decode the values before we feed them to the ClientRequest instance request.queryParameter((String)queryParamEntry.getKey(), URLDecoder.decode(parameterValue, "UTF-8")); } String uri = request.getUri(); ClientResponse clientResponse = request.httpMethod(httpMethod, new GenericType<InputStream>() {}); return clientResponse; } catch (WebApplicationException e) { throw e; } catch (Exception e) { logger.error("A problem occured while sending request to Astroboa Repository", e); throw new WebApplicationException(HttpURLConnection.HTTP_INTERNAL_ERROR); } } private String getBody(HttpServletRequest httpServletRequest) throws Exception { BufferedReader bufferedReader = null; StringBuilder stringBuilder = new StringBuilder(); try { bufferedReader = httpServletRequest.getReader(); char[] buffer = new char[4 * 1024]; // 4 KB char buffer int len; while ((len = bufferedReader.read(buffer, 0, buffer.length)) != -1) { stringBuilder.append(buffer, 0, len); } } catch (IOException e) { throw e; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { throw e; } } } return stringBuilder.toString(); } }