ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r1544231 - /ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java
Date Thu, 21 Nov 2013 15:58:26 GMT
Author: jawi
Date: Thu Nov 21 15:58:26 2013
New Revision: 1544231

URL: http://svn.apache.org/r1544231
Log:
ACE-436 - fixed possible resource leak:

- a possible resource leak could occur when handling package
  delivery to an agent that uses content-ranges during the
  agent update retrieval;
- restored the authorization functionality for this servlet,
  as this was not yet/no longer implemented, but should be,
  as this is a public endpoint;
- code formatting applied & compiler warnings removed.


Modified:
    ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java

Modified: ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java?rev=1544231&r1=1544230&r2=1544231&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java
(original)
+++ ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/AgentDeploymentServlet.java
Thu Nov 21 15:58:26 2013
@@ -18,6 +18,9 @@
  */
 package org.apache.ace.deployment.servlet;
 
+import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -41,11 +44,11 @@ import javax.xml.xpath.XPathFactory;
 
 import org.apache.ace.authentication.api.AuthenticationService;
 import org.apache.ace.connectionfactory.ConnectionFactory;
-import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.Version;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.User;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -58,27 +61,77 @@ public class AgentDeploymentServlet exte
     /** URL to the OBR that is used for finding versions of the agent. */
     private static final String KEY_OBR_URL = "obr.url";
 
+    private static final String XPATH_QUERY = "/repository/resource[@uri]";
+
     public static final String VERSIONS = "versions";
     public static final String BUNDLE_MIMETYPE = "application/octet-stream";
     public static final String TEXT_MIMETYPE = "text/plain";
-    
+
     // injected by Dependency Manager
-    private volatile DependencyManager m_dm; 
     private volatile LogService m_log;
     private volatile AuthenticationService m_authService;
     private volatile ConnectionFactory m_connectionFactory;
+    // See updated()
+    private boolean m_useAuth = false;
+    private URL m_obrURL;
 
-    private volatile boolean m_useAuth = false;
-    private static final String XPATH_QUERY = "/repository/resource[@uri]";
     private final String m_repositoryXML = "repository.xml";
-    private URL m_obrURL;
-    
+
+    /**
+     * Gets the actual text from a named item contained in the given node map.
+     * 
+     * @param map
+     *            the node map to get the named item from;
+     * @param name
+     *            the name of the item to get.
+     * @return the text of the named item, can be <code>null</code> in case the
named item does not exist, or has no
+     *         text.
+     */
+    private static String getNamedItemText(NamedNodeMap map, String name) {
+        Node namedItem = map.getNamedItem(name);
+        if (namedItem == null) {
+            return null;
+        }
+        else {
+            return namedItem.getTextContent();
+        }
+    }
+
+    @Override
+    public void updated(Dictionary settings) throws ConfigurationException {
+        if (settings != null) {
+            String useAuthString = (String) settings.get(KEY_USE_AUTHENTICATION);
+            if (useAuthString == null
+                || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString)))
{
+                throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid
value!");
+            }
+            boolean useAuth = Boolean.parseBoolean(useAuthString);
+            m_useAuth = useAuth;
+
+            String obrURL = (String) settings.get(KEY_OBR_URL);
+            try {
+                URL url = new URL(obrURL);
+                m_obrURL = url;
+            }
+            catch (MalformedURLException e) {
+                throw new ConfigurationException(KEY_OBR_URL, "Invalid value, not a URL.",
e);
+            }
+            if (obrURL == null) {
+                throw new ConfigurationException(KEY_OBR_URL, "Missing " +
+                    "value!");
+            }
+        }
+        else {
+            m_useAuth = false;
+            m_obrURL = null;
+        }
+    }
 
     @Override
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
         try {
             String[] pathElements = verifyAndGetPathElements(request.getPathInfo());
-            String targetID = pathElements[1]; // in the future we might use this for per
target approval
+            // String targetID = pathElements[1]; // in the future we might use this for
per target approval
             String agentID = pathElements[2];
             int numberOfElements = pathElements.length;
             if (numberOfElements == 4) {
@@ -93,55 +146,63 @@ public class AgentDeploymentServlet exte
             e.handleAsHttpError(response);
         }
     }
-    
-    private String[] verifyAndGetPathElements(String path) throws AceRestException {
-        if (path == null) {
-            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is
invalid, no path specified.");
-        }
-        String[] elements = path.split("/");
-        int numberOfElements = elements.length;
-        if ((numberOfElements < 4) || (numberOfElements > 5) || !VERSIONS.equals(elements[3]))
{
-            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI elements
are invalid: " + path);
-        }
-        return elements;
+
+    protected URLConnection openConnection(URL url) throws IOException {
+        return m_connectionFactory.createConnection(url);
     }
 
-    private List<Version> getVersions(String agentID) throws AceRestException {
-        try {
-            return getVersionsFromOBR(m_obrURL, agentID);
-        }
-        catch (XPathExpressionException e) {
-            throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown agent ("
+ agentID + ")");
+    @Override
+    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
+        if (!authenticate(req)) {
+            // Authentication failed; don't proceed with the original request...
+            resp.sendError(SC_UNAUTHORIZED);
         }
-        catch (IOException ioe) {
-            m_log.log(LogService.LOG_WARNING, "Error getting available versions.", ioe);
-            throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error
getting available versions.");
+        else {
+            // Authentication successful, proceed with original request...
+            super.service(req, resp);
         }
     }
 
-    private List<Version> getVersionsFromOBR(URL obrBaseUrl, String agentID) throws
XPathExpressionException, IOException {
-        InputStream input = null;
-        NodeList resources = getOBRNodeList(input);
-        List<Version> obrList = new ArrayList<Version>();
-        for (int nResource = 0; nResource < resources.getLength(); nResource++) {
-            Node resource = resources.item(nResource);
-            NamedNodeMap attr = resource.getAttributes();
-
-            String uri = getNamedItemText(attr, "uri");
-            if (uri == null || uri.equals("")) {
-                m_log.log(LogService.LOG_ERROR, "Skipping resource without uri from repository
" + obrBaseUrl);
-                continue;
+    /**
+     * Authenticates, if needed the user with the information from the given request.
+     * 
+     * @param request
+     *            the request to obtain the credentials from, cannot be <code>null</code>.
+     * @return <code>true</code> if the authentication was successful, <code>false</code>
otherwise.
+     */
+    private boolean authenticate(HttpServletRequest request) {
+        if (m_useAuth) {
+            User user = m_authService.authenticate(request);
+            if (user == null) {
+                m_log.log(LogService.LOG_INFO, "Authentication failure!");
             }
+            return (user != null);
+        }
+        return true;
+    }
 
-            String symbolicname = getNamedItemText(attr, "symbolicname");
-            if (agentID.equals(symbolicname)) {
-                Version version = new Version(getNamedItemText(attr, "version"));
-                obrList.add(version);
+    private void closeSilently(Closeable resource) {
+        try {
+            if (resource != null) {
+                resource.close();
             }
         }
-        Collections.sort(obrList);
-        return obrList;
+        catch (IOException e) {
+            m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request.
", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    private URL createOBRURL() throws MalformedURLException {
+        try {
+            return new URL(m_obrURL, m_repositoryXML);
+        }
+        catch (MalformedURLException e) {
+            m_log.log(LogService.LOG_ERROR, "Error retrieving repository.xml from " + m_obrURL);
+            throw e;
+        }
     }
+
     private InputStream getAgentFromOBR(URL obrBaseUrl, String agentID, Version version)
throws XPathExpressionException, IOException {
         InputStream input = null;
         NodeList resources = getOBRNodeList(input);
@@ -203,80 +264,71 @@ public class AgentDeploymentServlet exte
         return resources;
     }
 
-    private URL createOBRURL() throws MalformedURLException {
+    private List<Version> getVersions(String agentID) throws AceRestException {
         try {
-            return new URL(m_obrURL, m_repositoryXML);
-        }
-        catch (MalformedURLException e) {
-            m_log.log(LogService.LOG_ERROR, "Error retrieving repository.xml from " + m_obrURL);
-            throw e;
+            return getVersionsFromOBR(m_obrURL, agentID);
         }
-    }
-    protected URLConnection openConnection(URL url) throws IOException {
-        return m_connectionFactory.createConnection(url);
-    }
-    /**
-     * Gets the actual text from a named item contained in the given node map.
-     * 
-     * @param map the node map to get the named item from;
-     * @param name the name of the item to get.
-     * @return the text of the named item, can be <code>null</code> in case the
named item does not exist, or has no text.
-     */
-    private static String getNamedItemText(NamedNodeMap map, String name) {
-        Node namedItem = map.getNamedItem(name);
-        if (namedItem == null) {
-            return null;
+        catch (XPathExpressionException e) {
+            throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown agent ("
+ agentID + ")");
         }
-        else {
-            return namedItem.getTextContent();
+        catch (IOException ioe) {
+            m_log.log(LogService.LOG_WARNING, "Error getting available versions.", ioe);
+            throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error
getting available versions.");
         }
     }
-    
-    private void handleVersionsRequest(List<Version> versions, HttpServletResponse
response) throws AceRestException {
-        ServletOutputStream output = null;
 
-        response.setContentType(TEXT_MIMETYPE);
-        try {
-            output = response.getOutputStream();
-            for (Version version : versions) {
-                output.print(version.toString());
-                output.print("\n");
+    @SuppressWarnings("unchecked")
+    private List<Version> getVersionsFromOBR(URL obrBaseUrl, String agentID) throws
XPathExpressionException, IOException {
+        InputStream input = null;
+        NodeList resources = getOBRNodeList(input);
+        List<Version> obrList = new ArrayList<Version>();
+        for (int nResource = 0; nResource < resources.getLength(); nResource++) {
+            Node resource = resources.item(nResource);
+            NamedNodeMap attr = resource.getAttributes();
+
+            String uri = getNamedItemText(attr, "uri");
+            if (uri == null || uri.equals("")) {
+                m_log.log(LogService.LOG_ERROR, "Skipping resource without uri from repository
" + obrBaseUrl);
+                continue;
+            }
+
+            String symbolicname = getNamedItemText(attr, "symbolicname");
+            if (agentID.equals(symbolicname)) {
+                Version version = new Version(getNamedItemText(attr, "version"));
+                obrList.add(version);
             }
         }
-        catch (IOException e) {
-            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is
invalid");
-        }
-        finally {
-            tryClose(output);
-        }
+        Collections.sort(obrList);
+        return obrList;
     }
 
     private void handlePackageDelivery(String agentID, Version version, HttpServletRequest
request, HttpServletResponse response) throws AceRestException {
-        ServletOutputStream output = null;
+        InputStream is = null;
+        OutputStream os = null;
 
         try {
             // Wrap response to add support for range requests
             response = new ContentRangeResponseWrapper(request, response);
 
-            InputStream inputStream = null;
             try {
-                inputStream = getAgentFromOBR(m_obrURL, agentID, version);
-                if (inputStream == null) {
+                is = getAgentFromOBR(m_obrURL, agentID, version);
+                if (is == null) {
                     throw (AceRestException) new AceRestException(HttpServletResponse.SC_NOT_FOUND,
"Agent not found in OBR.");
                 }
             }
             catch (XPathExpressionException e) {
                 throw (AceRestException) new AceRestException(HttpServletResponse.SC_NOT_FOUND,
"Agent not found: error parsing OBR").initCause(e);
             }
+
             response.setContentType(BUNDLE_MIMETYPE);
-            output = response.getOutputStream();
+
+            os = response.getOutputStream();
             byte[] buffer = new byte[BUFFER_SIZE];
             int bytes;
-            while ((bytes = inputStream.read(buffer)) != -1) {
-                output.write(buffer, 0, bytes);
+            while ((bytes = is.read(buffer)) != -1) {
+                os.write(buffer, 0, bytes);
             }
-            output.flush();
-            inputStream.close();
+            os.flush();
         }
         catch (IllegalArgumentException e) {
             throw (AceRestException) new AceRestException(HttpServletResponse.SC_BAD_REQUEST,
"Request URI is invalid").initCause(e);
@@ -284,47 +336,40 @@ public class AgentDeploymentServlet exte
         catch (IOException e) {
             throw (AceRestException) new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Could not deliver package").initCause(e);
         }
+        finally {
+            closeSilently(is);
+            closeSilently(os);
+        }
     }
 
-    private void tryClose(OutputStream output) {
+    private void handleVersionsRequest(List<Version> versions, HttpServletResponse
response) throws AceRestException {
+        ServletOutputStream output = null;
+
+        response.setContentType(TEXT_MIMETYPE);
         try {
-            if (output != null) {
-                output.close();
+            output = response.getOutputStream();
+            for (Version version : versions) {
+                output.print(version.toString());
+                output.print("\n");
             }
         }
         catch (IOException e) {
-            m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request.
", e);
-            throw new RuntimeException(e);
+            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is
invalid");
+        }
+        finally {
+            closeSilently(output);
         }
     }
 
-    @Override
-    public void updated(Dictionary settings) throws ConfigurationException {
-        if (settings != null) {
-            String useAuthString = (String) settings.get(KEY_USE_AUTHENTICATION);
-            if (useAuthString == null
-                || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString)))
{
-                throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid
value!");
-            }
-            boolean useAuth = Boolean.parseBoolean(useAuthString);
-            m_useAuth = useAuth;
-            
-            String obrURL = (String) settings.get(KEY_OBR_URL);
-            try {
-                URL url = new URL(obrURL);
-                m_obrURL = url;
-            }
-            catch (MalformedURLException e) {
-                throw new ConfigurationException(KEY_OBR_URL, "Invalid value, not a URL.",
e);
-            }
-            if (obrURL == null) {
-                throw new ConfigurationException(KEY_OBR_URL, "Missing " +
-                		"value!");
-            }
+    private String[] verifyAndGetPathElements(String path) throws AceRestException {
+        if (path == null) {
+            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is
invalid, no path specified.");
         }
-        else {
-            m_useAuth = false;
-            m_obrURL = null;
+        String[] elements = path.split("/");
+        int numberOfElements = elements.length;
+        if ((numberOfElements < 4) || (numberOfElements > 5) || !VERSIONS.equals(elements[3]))
{
+            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI elements
are invalid: " + path);
         }
+        return elements;
     }
 }



Mime
View raw message