You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2013/11/05 14:04:20 UTC

svn commit: r1538979 - in /ace/trunk/org.apache.ace.client.repository: src/org/apache/ace/client/repository/helper/configuration/impl/ src/org/apache/ace/client/repository/helper/user/impl/ test/ test/org/apache/ace/client/repository/helper/user/ test/...

Author: jawi
Date: Tue Nov  5 13:04:19 2013
New Revision: 1538979

URL: http://svn.apache.org/r1538979
Log:
ACE-114 - better error handler for UserAdminHelper:

- same solution as for ACE-113.


Added:
    ace/trunk/org.apache.ace.client.repository/test/invalidUserAdmin.xml
    ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/
    ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/
    ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/UserHelperImplTest.java
    ace/trunk/org.apache.ace.client.repository/test/validUserAdmin.xml
    ace/trunk/org.apache.ace.client.repository/test/validUserAdminWithComment.xml
Modified:
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java?rev=1538979&r1=1538978&r2=1538979&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java Tue Nov  5 13:04:19 2013
@@ -37,7 +37,7 @@ import org.osgi.service.log.LogService;
 public class Activator extends DependencyActivatorBase {
 
     @Override
-    public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+    public void init(BundleContext context, DependencyManager manager) throws Exception {
         Dictionary<String, String> props = new Hashtable<String, String>();
         props.put(ArtifactObject.KEY_MIMETYPE, ConfigurationHelper.MIMETYPE);
 
@@ -55,7 +55,7 @@ public class Activator extends Dependenc
     }
 
     @Override
-    public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+    public void destroy(BundleContext context, DependencyManager manager) throws Exception {
         // Nothing to do
     }
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java?rev=1538979&r1=1538978&r2=1538979&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java Tue Nov  5 13:04:19 2013
@@ -207,10 +207,7 @@ public class ConfigurationHelperImpl imp
             reader.parse(new InputSource(input));
         }
         catch (Exception e) {
-            String namespace = handler.getMetaDataNamespace();
-            if (NAMESPACE_1_0.equals(namespace) || NAMESPACE_1_1.equals(namespace) || NAMESPACE_1_2.equals(namespace)) {
-                return MIMETYPE;
-            }
+            // Ignore, we're only interested in the results contained in the handler...
         }
         finally {
             if (input != null) {
@@ -218,9 +215,14 @@ public class ConfigurationHelperImpl imp
                     input.close();
                 }
                 catch (IOException e) {
+                    // Ignore...
                 }
             }
         }
+        String namespace = handler.getMetaDataNamespace();
+        if (NAMESPACE_1_0.equals(namespace) || NAMESPACE_1_1.equals(namespace) || NAMESPACE_1_2.equals(namespace)) {
+            return MIMETYPE;
+        }
         return null;
     }
 

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java?rev=1538979&r1=1538978&r2=1538979&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java Tue Nov  5 13:04:19 2013
@@ -29,6 +29,7 @@ import org.apache.felix.dm.DependencyAct
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.service.log.LogService;
 
 /**
  * Activator class for the UserAdmin ArtifactHelper.
@@ -36,23 +37,26 @@ import org.osgi.framework.Constants;
 public class Activator extends DependencyActivatorBase {
 
     @Override
-    public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+    public void init(BundleContext context, DependencyManager manager) throws Exception {
         Properties props = new Properties();
         props.put(Constants.SERVICE_RANKING, 10);
         props.put(ArtifactObject.KEY_MIMETYPE, UserAdminHelper.MIMETYPE);
 
         UserHelperImpl helperImpl = new UserHelperImpl();
         manager.add(createComponent()
-            .setInterface(new String[]{ ArtifactHelper.class.getName(), ArtifactRecognizer.class.getName() }, props)
+            .setInterface(new String[] { ArtifactHelper.class.getName(), ArtifactRecognizer.class.getName() }, props)
             .setImplementation(helperImpl)
             .add(createServiceDependency()
                 .setService(ConnectionFactory.class)
                 .setRequired(true))
+            .add(createServiceDependency()
+                .setService(LogService.class)
+                .setRequired(false))
             );
     }
 
     @Override
-    public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+    public void destroy(BundleContext context, DependencyManager manager) throws Exception {
         // Nothing to do
     }
-}
\ No newline at end of file
+}

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java?rev=1538979&r1=1538978&r2=1538979&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java Tue Nov  5 13:04:19 2013
@@ -19,12 +19,16 @@
 package org.apache.ace.client.repository.helper.user.impl;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
 import org.apache.ace.client.repository.helper.ArtifactRecognizer;
@@ -33,16 +37,125 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.helper.user.UserAdminHelper;
 import org.apache.ace.client.repository.object.ArtifactObject;
 import org.apache.ace.connectionfactory.ConnectionFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
+import org.osgi.service.log.LogService;
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
 
 public class UserHelperImpl implements ArtifactRecognizer, UserAdminHelper {
 
+    static class LoggingErrorHandler implements ErrorHandler {
+        private final ArtifactResource m_resource;
+        private final LogService m_log;
+
+        public LoggingErrorHandler(ArtifactResource resource, LogService log) {
+            m_resource = resource;
+            m_log = log;
+        }
+
+        @Override
+        public void warning(SAXParseException exception) throws SAXException {
+            log(LogService.LOG_WARNING, "Artifact '" + getName() + "' contains a warning!", exception);
+        }
+
+        @Override
+        public void error(SAXParseException exception) throws SAXException {
+            log(LogService.LOG_ERROR, "Artifact '" + getName() + "' contains an error!", exception);
+        }
+
+        @Override
+        public void fatalError(SAXParseException exception) throws SAXException {
+            log(LogService.LOG_ERROR, "Artifact '" + getName() + "' contains a fatal error!", exception);
+        }
+
+        private String getName() {
+            URL url = m_resource.getURL();
+            try {
+                if ("file".equals(url.getProtocol())) {
+                    return new File(url.toURI()).getName();
+                }
+            }
+            catch (URISyntaxException exception) {
+                // Ignore; fall through to return complete name...
+            }
+            return url.getFile();
+        }
+
+        private void log(int level, String msg, Exception exception) {
+            if (m_log != null) {
+                m_log.log(level, msg.concat(" ").concat(exception.getMessage()), exception);
+            }
+        }
+    }
+
+    static class UserAdminXmlHandler extends DefaultHandler {
+        private boolean m_appearsValid = false;
+        private boolean m_rolesTagSeen = false;
+        private boolean m_groupOrUserTagSeen = false;
+
+        public boolean appearsValid() {
+            return m_appearsValid;
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+            if (m_rolesTagSeen && isQName("roles", qName)) {
+                m_rolesTagSeen = false;
+            }
+            if (m_groupOrUserTagSeen && (isQName("group", qName) || isQName("user", qName))) {
+                m_groupOrUserTagSeen = false;
+            }
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+            if (isQName("roles", qName)) {
+                m_rolesTagSeen = true;
+            }
+            else if (m_rolesTagSeen) {
+                if (!m_groupOrUserTagSeen) {
+                    if (isQName("group", qName) || isQName("user", qName)) {
+                        m_groupOrUserTagSeen = true;
+                        m_appearsValid = true;
+                    }
+                    else {
+                        m_appearsValid = false;
+                        // Unexpected tag...
+                        throw new SAXException("Done");
+                    }
+                }
+                else {
+                    // inside a group or user tag we do not care about the tags...
+                }
+            }
+        }
+
+        private boolean isQName(String expected, String name) {
+            return (name != null) && (expected.equals(name) || name.endsWith(":".concat(expected)));
+        }
+    }
+
+    private final SAXParserFactory m_saxParserFactory;
     // Injected by Dependency Manager
     private volatile ConnectionFactory m_connectionFactory;
+    private volatile LogService m_log;
+
     // Created in #start()
     private volatile VelocityArtifactPreprocessor m_artifactPreprocessor;
 
+    /**
+     * Creates a new {@link UserHelperImpl} instance.
+     */
+    public UserHelperImpl() {
+        m_saxParserFactory = SAXParserFactory.newInstance();
+        m_saxParserFactory.setNamespaceAware(false);
+        m_saxParserFactory.setValidating(false);
+    }
+
     public boolean canHandle(String mimetype) {
         return MIMETYPE.equals(mimetype);
     }
@@ -63,26 +176,32 @@ public class UserHelperImpl implements A
     }
 
     public String recognize(ArtifactResource artifact) {
+        UserAdminXmlHandler handler = new UserAdminXmlHandler();
+        InputStream input = null;
         try {
-            InputStream in = artifact.openStream();
-            
-            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
-            Node root = doc.getFirstChild();
-            if (!root.getNodeName().equals("roles")) {
-                return null;
-            }
-            for (Node node = root.getFirstChild(); root != null; root = root.getNextSibling()) {
-                if (!node.getNodeName().equals("group") && !node.getNodeName().equals("user") && !node.getNodeName().equals("#text")) {
-                    return null;
-                }
-            }
-            return MIMETYPE;
+            input = artifact.openStream();
+            SAXParser parser = m_saxParserFactory.newSAXParser();
+
+            XMLReader reader = parser.getXMLReader();
+            reader.setErrorHandler(new LoggingErrorHandler(artifact, m_log));
+            reader.setContentHandler(handler);
+            reader.parse(new InputSource(input));
         }
         catch (Exception e) {
-            // Does not matter.
+            // Ignore, we're only detecting whether or not it is a valid XML file that resembles our scheme...
+        }
+        finally {
+            if (input != null) {
+                try {
+                    input.close();
+                }
+                catch (IOException exception) {
+                    // Ignore...
+                }
+            }
         }
 
-        return null;
+        return handler.appearsValid() ? MIMETYPE : null;
     }
 
     public boolean canUse(ArtifactObject object) {
@@ -107,17 +226,17 @@ public class UserHelperImpl implements A
     }
 
     public String[] getDefiningKeys() {
-        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+        return new String[] { ArtifactObject.KEY_ARTIFACT_NAME };
     }
 
     public String[] getMandatoryAttributes() {
-        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+        return new String[] { ArtifactObject.KEY_ARTIFACT_NAME };
     }
 
     public ArtifactPreprocessor getPreprocessor() {
         return m_artifactPreprocessor;
     }
-    
+
     public String getExtension(ArtifactResource artifact) {
         return ".xml";
     }
@@ -134,6 +253,14 @@ public class UserHelperImpl implements A
      */
     protected void stop() {
         m_artifactPreprocessor = null;
-        
+
+    }
+
+    /**
+     * @param log
+     *            the log service to set, can be <code>null</code>.
+     */
+    final void setLog(LogService log) {
+        m_log = log;
     }
-}
\ No newline at end of file
+}

Added: ace/trunk/org.apache.ace.client.repository/test/invalidUserAdmin.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/test/invalidUserAdmin.xml?rev=1538979&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/test/invalidUserAdmin.xml (added)
+++ ace/trunk/org.apache.ace.client.repository/test/invalidUserAdmin.xml Tue Nov  5 13:04:19 2013
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<roles>
+	<group name="group1">
+		<properties>
+			<type>userGroup</type>
+		</properties>
+	</group>
+	<user name="user">
+		<properties>
+			<username>user</username>
+		</properties>
+		<credentials>
+			<password>secret</password>
+		</credentials>
+		<memberof>group1</memberof>
+	</user>
+	<foo></foo>
+</roles>

Added: ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/UserHelperImplTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/UserHelperImplTest.java?rev=1538979&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/UserHelperImplTest.java (added)
+++ ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/helper/user/impl/UserHelperImplTest.java Tue Nov  5 13:04:19 2013
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.user.impl;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.ace.client.repository.helper.ArtifactResource;
+import org.osgi.service.log.LogService;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test cases for {@link UserHelperImpl}.
+ */
+public class UserHelperImplTest {
+    private LogService m_mockLogService;
+
+    @Test(groups = { UNIT })
+    public void testCanHandleCommentBeforeRoot() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("validUserAdminWithComment.xml"));
+        Assert.assertNotNull(mime);
+
+        verifyZeroInteractions(m_mockLogService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testInvalidUserAdminXmlContent() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("invalidUserAdmin.xml"));
+        Assert.assertNull(mime);
+
+        verifyZeroInteractions(m_mockLogService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testInvalidXmlContentNotRecognized() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("invalid.xml"));
+        Assert.assertNull(mime);
+
+        verify(m_mockLogService, times(1)).log(anyInt(), anyString(), any(Throwable.class));
+        verifyNoMoreInteractions(m_mockLogService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testNoUserAdminXmlContent() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("valid10.xml"));
+        Assert.assertNull(mime);
+
+        verifyZeroInteractions(m_mockLogService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testNoXmlContentNotRecognized() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("invalid.txt"));
+        Assert.assertNull(mime);
+
+        verify(m_mockLogService, times(1)).log(anyInt(), anyString(), any(Throwable.class));
+        verifyNoMoreInteractions(m_mockLogService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testValidUserAdminXmlContent() throws Exception {
+        UserHelperImpl uh = createUserHelper();
+        String mime = uh.recognize(convertToArtifactResource("validUserAdmin.xml"));
+        Assert.assertNotNull(mime);
+
+        verifyZeroInteractions(m_mockLogService);
+    }
+
+    private ArtifactResource convertToArtifactResource(final String res) {
+        if (res == null) {
+            return null;
+        }
+
+        final URL url = getClass().getClassLoader().getResource("./" + res);
+        return new ArtifactResource() {
+            @Override
+            public long getSize() throws IOException {
+                return -1L;
+            }
+
+            public URL getURL() {
+                return url;
+            }
+
+            public InputStream openStream() throws IOException {
+                return getURL().openStream();
+            }
+        };
+    }
+
+    /**
+     * @return a new {@link UserHelperImpl} instance, never <code>null</code>.
+     */
+    private UserHelperImpl createUserHelper() {
+        m_mockLogService = mock(LogService.class);
+
+        UserHelperImpl uh = new UserHelperImpl();
+        uh.setLog(m_mockLogService);
+        return uh;
+    }
+}

Added: ace/trunk/org.apache.ace.client.repository/test/validUserAdmin.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/test/validUserAdmin.xml?rev=1538979&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/test/validUserAdmin.xml (added)
+++ ace/trunk/org.apache.ace.client.repository/test/validUserAdmin.xml Tue Nov  5 13:04:19 2013
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<roles>
+	<group name="group1">
+		<properties>
+			<type>userGroup</type>
+		</properties>
+	</group>
+	<user name="user">
+		<properties>
+			<username>user</username>
+		</properties>
+		<credentials>
+			<password>secret</password>
+		</credentials>
+		<memberof>group1</memberof>
+	</user>
+</roles>

Added: ace/trunk/org.apache.ace.client.repository/test/validUserAdminWithComment.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/test/validUserAdminWithComment.xml?rev=1538979&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/test/validUserAdminWithComment.xml (added)
+++ ace/trunk/org.apache.ace.client.repository/test/validUserAdminWithComment.xml Tue Nov  5 13:04:19 2013
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+	This is valid
+-->
+<roles>
+	<group name="group1">
+		<properties>
+			<type>userGroup</type>
+		</properties>
+	</group>
+	<user name="user">
+		<properties>
+			<username>user</username>
+		</properties>
+		<credentials>
+			<password>secret</password>
+		</credentials>
+		<memberof>group1</memberof>
+	</user>
+</roles>