Search in sources :

Example 1 with RemoteConnectorResponse

use of org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse in project alfresco-remote-api by Alfresco.

the class LocalWebScriptConnectorServiceImpl method executeRequest.

/**
 * Executes the specified request, and return the response
 */
public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException, RemoteConnectorClientException, RemoteConnectorServerException {
    // Convert the request object
    RemoteConnectorRequestImpl requestImpl = (RemoteConnectorRequestImpl) request;
    Request req = new Request(request.getMethod(), request.getURL());
    req.setType(request.getContentType());
    if (request.getRequestBody() != null) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        requestImpl.getRequestBody().writeRequest(baos);
        req.setBody(baos.toByteArray());
    }
    // Log
    if (logger.isInfoEnabled())
        logger.info("Performing local " + request.getMethod() + " request to " + request.getURL());
    // Capture the user details, as they may be changed during the request processing
    Authentication fullAuth = AuthenticationUtil.getFullAuthentication();
    String runAsUser = AuthenticationUtil.getRunAsUser();
    // If they've specified Authentication details in the request, clear our security context
    // and switch to that user, to avoid our context confusing the real request
    Header authHeader = null;
    Map<String, String> headers = new HashMap<String, String>();
    for (Header header : request.getRequestHeaders()) {
        if (header.getName().equals("Authorization")) {
            authHeader = header;
        }
        headers.put(header.getName(), header.getValue());
    }
    if (authHeader != null) {
        AuthenticationUtil.clearCurrentSecurityContext();
        if (logger.isDebugEnabled())
            logger.debug("HTTP Authorization found for the request, clearing security context, Auth is " + authHeader);
    }
    req.setHeaders(headers);
    // Execute the request against the WebScript Test Framework
    Response resp;
    try {
        resp = helper.sendRequest(req, -1);
    } catch (Exception e) {
        throw new AlfrescoRuntimeException("Problem requesting", e);
    }
    // Reset the user details, now we're done performing the request
    AuthenticationUtil.setFullAuthentication(fullAuth);
    if (runAsUser != null && !runAsUser.equals(fullAuth.getName())) {
        AuthenticationUtil.setRunAsUser(runAsUser);
    }
    // Log
    if (logger.isInfoEnabled())
        logger.info("Response to request was " + resp.getStatus() + " - " + resp);
    // Check the status for specific typed exceptions
    if (resp.getStatus() == Status.STATUS_UNAUTHORIZED) {
        throw new AuthenticationException("Not Authorized to access this resource");
    }
    if (resp.getStatus() == Status.STATUS_FORBIDDEN) {
        throw new AuthenticationException("Forbidden to access this resource");
    }
    // Check for failures where we don't care about the response body
    if (resp.getStatus() >= 500 && resp.getStatus() <= 599) {
        throw new RemoteConnectorServerException(resp.getStatus(), "(not available)");
    }
    // Convert the response into our required format
    String charset = null;
    String contentType = resp.getContentType();
    if (contentType != null && contentType.contains("charset=")) {
        int splitAt = contentType.indexOf("charset=") + "charset=".length();
        charset = contentType.substring(splitAt);
    }
    InputStream body = new ByteArrayInputStream(resp.getContentAsByteArray());
    // TODO Can't easily get the list...
    Header[] respHeaders = new Header[0];
    RemoteConnectorResponse response = new RemoteConnectorResponseImpl(request, contentType, charset, resp.getStatus(), respHeaders, body);
    // If it's a client error, let them know what went wrong
    if (resp.getStatus() >= 400 && resp.getStatus() <= 499) {
        throw new RemoteConnectorClientException(resp.getStatus(), "(not available)", response);
    }
    // Otherwise return the response for processing
    return response;
}
Also used : HashMap(java.util.HashMap) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) WebScriptServletRequest(org.springframework.extensions.webscripts.servlet.WebScriptServletRequest) RemoteConnectorRequest(org.alfresco.service.cmr.remoteconnector.RemoteConnectorRequest) Request(org.springframework.extensions.webscripts.TestWebScriptServer.Request) ByteArrayOutputStream(java.io.ByteArrayOutputStream) RemoteConnectorResponse(org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse) ParseException(org.json.simple.parser.ParseException) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) IOException(java.io.IOException) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) RemoteConnectorClientException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException) RemoteConnectorServerException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException) Response(org.springframework.extensions.webscripts.TestWebScriptServer.Response) WebScriptServletResponse(org.springframework.extensions.webscripts.servlet.WebScriptServletResponse) RemoteConnectorResponse(org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse) RemoteConnectorClientException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException) Header(org.apache.commons.httpclient.Header) ByteArrayInputStream(java.io.ByteArrayInputStream) Authentication(net.sf.acegisecurity.Authentication) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) RemoteConnectorServerException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException)

Example 2 with RemoteConnectorResponse

use of org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse in project alfresco-repository by Alfresco.

the class RemoteConnectorServiceImpl method doExecuteJSONRequest.

public static JSONObject doExecuteJSONRequest(RemoteConnectorRequest request, RemoteConnectorService service) throws ParseException, IOException, AuthenticationException {
    // Set as JSON
    request.setContentType(MimetypeMap.MIMETYPE_JSON);
    // Perform the request
    RemoteConnectorResponse response = service.executeRequest(request);
    // Parse this as JSON
    JSONParser parser = new JSONParser();
    String jsonText = response.getResponseBodyAsString();
    Object json = parser.parse(jsonText);
    // Check it's the right type and return
    if (json instanceof JSONObject) {
        return (JSONObject) json;
    } else {
        throw new ParseException(0, json);
    }
}
Also used : JSONObject(org.json.simple.JSONObject) JSONParser(org.json.simple.parser.JSONParser) JSONObject(org.json.simple.JSONObject) ParseException(org.json.simple.parser.ParseException) RemoteConnectorResponse(org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse)

Example 3 with RemoteConnectorResponse

use of org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse in project alfresco-repository by Alfresco.

the class RemoteConnectorServiceImpl method executeRequest.

/**
 * Executes the specified request, and return the response
 */
public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException, RemoteConnectorClientException, RemoteConnectorServerException {
    RemoteConnectorRequestImpl reqImpl = (RemoteConnectorRequestImpl) request;
    HttpMethodBase httpRequest = reqImpl.getMethodInstance();
    // Attach the headers to the request
    for (Header hdr : request.getRequestHeaders()) {
        httpRequest.addRequestHeader(hdr);
    }
    // Attach the body, if possible
    if (httpRequest instanceof EntityEnclosingMethod) {
        if (request.getRequestBody() != null) {
            ((EntityEnclosingMethod) httpRequest).setRequestEntity(reqImpl.getRequestBody());
        }
    }
    // Grab our thread local HttpClient instance
    // Remember - we must then clean it up!
    HttpClient httpClient = HttpClientHelper.getHttpClient();
    // The url should already be vetted by the RemoteConnectorRequest
    URL url = new URL(request.getURL());
    // Use the appropriate Proxy Host if required
    if (httpProxyHost != null && url.getProtocol().equals("http") && HttpClientHelper.requiresProxy(url.getHost())) {
        httpClient.getHostConfiguration().setProxyHost(httpProxyHost);
        if (logger.isDebugEnabled()) {
            logger.debug(" - using HTTP proxy host for: " + url);
        }
        if (httpProxyCredentials != null) {
            httpClient.getState().setProxyCredentials(httpAuthScope, httpProxyCredentials);
            if (logger.isDebugEnabled()) {
                logger.debug(" - using HTTP proxy credentials for proxy: " + httpProxyHost.getHostName());
            }
        }
    } else if (httpsProxyHost != null && url.getProtocol().equals("https") && HttpClientHelper.requiresProxy(url.getHost())) {
        httpClient.getHostConfiguration().setProxyHost(httpsProxyHost);
        if (logger.isDebugEnabled()) {
            logger.debug(" - using HTTPS proxy host for: " + url);
        }
        if (httpsProxyCredentials != null) {
            httpClient.getState().setProxyCredentials(httpsAuthScope, httpsProxyCredentials);
            if (logger.isDebugEnabled()) {
                logger.debug(" - using HTTPS proxy credentials for proxy: " + httpsProxyHost.getHostName());
            }
        }
    } else {
        // host should not be proxied remove any configured proxies
        httpClient.getHostConfiguration().setProxyHost(null);
        httpClient.getState().clearProxyCredentials();
    }
    // Log what we're doing
    if (logger.isDebugEnabled()) {
        logger.debug("Performing " + request.getMethod() + " request to " + request.getURL());
        for (Header hdr : request.getRequestHeaders()) {
            logger.debug("Header: " + hdr);
        }
        Object requestBody = null;
        if (request != null) {
            requestBody = request.getRequestBody();
        }
        if (requestBody != null && requestBody instanceof StringRequestEntity) {
            StringRequestEntity re = (StringRequestEntity) request.getRequestBody();
            // remove credentials from logs, such as "username":"John.Doe@test.com" and "password":"123456abc"
            // the strings can include double quotes, therefore we should check for proper end, it can be either
            // a comma "," or "}"
            // REPO-1471
            // returns a new string, should be safe to modify
            String payload = re.getContent();
            String usernameString = "\"username\"";
            String passwordString = "\"password\"";
            String hiddenString = "\"<hidden>\"";
            List<String> matches = new LinkedList<>();
            Matcher m = Pattern.compile(usernameString + ":\"(.+)\",|" + usernameString + ":\"(.+)\"}|" + passwordString + ":\"(.+)\",|" + passwordString + ":\"(.+)\"}").matcher(payload);
            while (m.find()) {
                matches.add(m.group());
            }
            for (String match : matches) {
                if (match.contains(usernameString)) {
                    payload = payload.replace(match.substring(// 1 is semicolon
                    match.indexOf(usernameString) + usernameString.length() + 1, // 1 is a double quote
                    match.lastIndexOf("\"") + 1), hiddenString);
                } else if (match.contains(passwordString)) {
                    payload = payload.replace(match.substring(// 1 is semicolon
                    match.indexOf(passwordString) + passwordString.length() + 1, // 1 is a double quote
                    match.lastIndexOf("\"") + 1), hiddenString);
                }
            }
            logger.debug("Payload (string): " + payload);
        } else if (requestBody != null && requestBody instanceof ByteArrayRequestEntity) {
            ByteArrayRequestEntity re = (ByteArrayRequestEntity) request.getRequestBody();
            logger.debug("Payload (byte array): " + re.getContent().toString());
        } else {
            logger.debug("Payload is not of a readable type.");
        }
    }
    // Perform the request, and wrap the response
    int status = -1;
    String statusText = null;
    RemoteConnectorResponse response = null;
    try {
        status = httpClient.executeMethod(httpRequest);
        statusText = httpRequest.getStatusText();
        Header[] responseHdrs = httpRequest.getResponseHeaders();
        Header responseContentTypeH = httpRequest.getResponseHeader(RemoteConnectorRequestImpl.HEADER_CONTENT_TYPE);
        String responseCharSet = httpRequest.getResponseCharSet();
        String responseContentType = (responseContentTypeH != null ? responseContentTypeH.getValue() : null);
        if (logger.isDebugEnabled()) {
            logger.debug("response url=" + request.getURL() + ", length =" + httpRequest.getResponseContentLength() + ", responceContentType " + responseContentType + ", statusText =" + statusText);
        }
        // If we can close immediately, it makes cleanup simpler and fool-proof
        if (httpRequest.getResponseContentLength() > MAX_BUFFER_RESPONSE_SIZE || httpRequest.getResponseContentLength() == -1) {
            if (logger.isTraceEnabled()) {
                logger.trace("large response (or don't know length) url=" + request.getURL());
            }
            // Need to wrap the InputStream in something that'll close
            InputStream wrappedStream = new HttpClientReleasingInputStream(httpRequest);
            httpRequest = null;
            // Now build the response
            response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet, status, responseHdrs, wrappedStream);
        } else {
            if (logger.isTraceEnabled()) {
                logger.debug("small response for url=" + request.getURL());
            }
            // Fairly small response, just keep the bytes and make life simple
            response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet, status, responseHdrs, httpRequest.getResponseBody());
            // Now we have the bytes, we can close the HttpClient resources
            httpRequest.releaseConnection();
            httpRequest = null;
        }
    } finally {
        // This is important because we use a thread local HttpClient instance
        if (httpRequest != null) {
            httpRequest.releaseConnection();
            httpRequest = null;
        }
    }
    // Log the response
    if (logger.isDebugEnabled())
        logger.debug("Response was " + status + " " + statusText);
    // Decide if we should throw an exception
    if (status >= 300) {
        // Tidy if needed
        if (httpRequest != null)
            httpRequest.releaseConnection();
        // Specific exceptions
        if (status == Status.STATUS_FORBIDDEN || status == Status.STATUS_UNAUTHORIZED) {
            // TODO Need to get error message into the AuthenticationException
            throw new AuthenticationException(statusText);
        }
        // Server side exceptions
        if (status >= 500 && status <= 599) {
            logger.error("executeRequest: remote connector server exception: [" + status + "] " + statusText);
            throw new RemoteConnectorServerException(status, statusText);
        }
        if (status == Status.STATUS_PRECONDITION_FAILED) {
            logger.error("executeRequest: remote connector client exception: [" + status + "] " + statusText);
            throw new RemoteConnectorClientException(status, statusText, response);
        } else {
            // Client request exceptions
            if (httpRequest != null) {
                // Response wasn't too big and is available, supply it
                logger.error("executeRequest: remote connector client exception: [" + status + "] " + statusText);
                throw new RemoteConnectorClientException(status, statusText, response);
            } else {
                // Response was too large, report without it
                logger.error("executeRequest: remote connector client exception: [" + status + "] " + statusText);
                throw new RemoteConnectorClientException(status, statusText, null);
            }
        }
    }
    // So, return our created response
    return response;
}
Also used : StringRequestEntity(org.apache.commons.httpclient.methods.StringRequestEntity) HttpMethodBase(org.apache.commons.httpclient.HttpMethodBase) Matcher(java.util.regex.Matcher) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) FilterInputStream(java.io.FilterInputStream) InputStream(java.io.InputStream) EntityEnclosingMethod(org.apache.commons.httpclient.methods.EntityEnclosingMethod) RemoteConnectorResponse(org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse) URL(java.net.URL) LinkedList(java.util.LinkedList) RemoteConnectorClientException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException) Header(org.apache.commons.httpclient.Header) HttpClient(org.apache.commons.httpclient.HttpClient) JSONObject(org.json.simple.JSONObject) RemoteConnectorServerException(org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException) ByteArrayRequestEntity(org.apache.commons.httpclient.methods.ByteArrayRequestEntity)

Aggregations

RemoteConnectorResponse (org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse)3 InputStream (java.io.InputStream)2 AuthenticationException (org.alfresco.repo.security.authentication.AuthenticationException)2 RemoteConnectorClientException (org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException)2 RemoteConnectorServerException (org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException)2 Header (org.apache.commons.httpclient.Header)2 JSONObject (org.json.simple.JSONObject)2 ParseException (org.json.simple.parser.ParseException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 FilterInputStream (java.io.FilterInputStream)1 IOException (java.io.IOException)1 URL (java.net.URL)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 Matcher (java.util.regex.Matcher)1 Authentication (net.sf.acegisecurity.Authentication)1 AlfrescoRuntimeException (org.alfresco.error.AlfrescoRuntimeException)1 RemoteConnectorRequest (org.alfresco.service.cmr.remoteconnector.RemoteConnectorRequest)1 HttpClient (org.apache.commons.httpclient.HttpClient)1