This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicemix-specs.git


The following commit(s) were added to refs/heads/master by this push:
     new c181ce0  SM-4383 activation-api spec modification to CommandMap leads 
to invalid registrations and memory leak
     new d8375fd  Merge pull request #20 from oliverlietz/SM-4383
c181ce0 is described below

commit c181ce0ac1905f21a5951c650b6410af4e9f2ee7
Author: Oliver Lietz <[email protected]>
AuthorDate: Wed May 5 19:49:29 2021 +0200

    SM-4383 activation-api spec modification to CommandMap leads to invalid 
registrations and memory leak
    
    add fixes and tests for 1.2.1
---
 activation-api-1.2.1/pom.xml                       | 28 ++++++++
 .../java/javax/activation/MailcapCommandMap.java   | 12 +++-
 .../servicemix/specs/activation/Activator.java     |  1 +
 .../ITBugDuplicatedMaincapRegistrations.java       | 49 ++++++++++++++
 .../specs/activation/ITClearCurrentBundle.java     | 75 ++++++++++++++++++++++
 .../src/test/resources/mailcap.example             |  2 +
 6 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/activation-api-1.2.1/pom.xml b/activation-api-1.2.1/pom.xml
index 193d80b..b5cce13 100644
--- a/activation-api-1.2.1/pom.xml
+++ b/activation-api-1.2.1/pom.xml
@@ -58,6 +58,18 @@
             <version>1.4.0</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>3.9.0</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
@@ -131,6 +143,22 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>3.0.0-M5</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                        <configuration>
+                            
<argLine>-Djava.endorsed.dirs=${project.build.directory},${maven.dependency.org.osgi.core.jar.path}</argLine>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git 
a/activation-api-1.2.1/src/main/java/javax/activation/MailcapCommandMap.java 
b/activation-api-1.2.1/src/main/java/javax/activation/MailcapCommandMap.java
index 536083f..c916e63 100644
--- a/activation-api-1.2.1/src/main/java/javax/activation/MailcapCommandMap.java
+++ b/activation-api-1.2.1/src/main/java/javax/activation/MailcapCommandMap.java
@@ -281,11 +281,21 @@ public class MailcapCommandMap extends CommandMap {
                     cmdList = new ArrayList();
                     allCommands.put(mimeType, cmdList);
                 }
-                cmdList.add(info);
+                addUnique(cmdList, info);
             }
         }
     }
 
+    private void addUnique(List commands, CommandInfo newCommand) {
+        for (Iterator i = commands.iterator(); i.hasNext();) {
+            CommandInfo info = (CommandInfo)i.next();
+            if (info.getCommandName().equals(newCommand.getCommandName())
+                    && 
info.getCommandClass().equals(newCommand.getCommandClass())) {
+                return;
+            }
+        }
+        commands.add(newCommand);
+    }
 
     /**
      * Add a command to a target command list (preferred or fallback).
diff --git 
a/activation-api-1.2.1/src/main/java/org/apache/servicemix/specs/activation/Activator.java
 
b/activation-api-1.2.1/src/main/java/org/apache/servicemix/specs/activation/Activator.java
index fc2643f..30ff5df 100644
--- 
a/activation-api-1.2.1/src/main/java/org/apache/servicemix/specs/activation/Activator.java
+++ 
b/activation-api-1.2.1/src/main/java/org/apache/servicemix/specs/activation/Activator.java
@@ -99,6 +99,7 @@ public class Activator extends 
org.apache.servicemix.specs.locator.Activator {
                     commandMap.addMailcap(line, mailcap.bundle);
                 }
             }
+            commandMap.addMailcap("", null);
             CommandMap.setDefaultCommandMap(commandMap);
         } finally {
             Thread.currentThread().setContextClassLoader(tccl);
diff --git 
a/activation-api-1.2.1/src/test/java/javax/activation/ITBugDuplicatedMaincapRegistrations.java
 
b/activation-api-1.2.1/src/test/java/javax/activation/ITBugDuplicatedMaincapRegistrations.java
new file mode 100644
index 0000000..4bb4749
--- /dev/null
+++ 
b/activation-api-1.2.1/src/test/java/javax/activation/ITBugDuplicatedMaincapRegistrations.java
@@ -0,0 +1,49 @@
+/*
+ * 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 javax.activation;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+
+/**
+ * SM-4383. Filter out duplicate registrations of a command.
+ */
+public class ITBugDuplicatedMaincapRegistrations {
+
+    private static final String MIMETYPE = "example/sm-4383";
+
+    private static final String MAILCAP = MIMETYPE+";; 
x-java-content-handler=some.value";
+
+    @Test
+    public void testFilterDuplicates() {
+        MailcapCommandMap mc = new MailcapCommandMap();
+
+        assertEquals(0, mc.getAllCommands(MIMETYPE).length);
+
+        mc.addMailcap(MAILCAP);
+        mc.addMailcap(MAILCAP);
+        assertEquals(1, mc.getAllCommands(MIMETYPE).length);
+
+        mc.addMailcap(MAILCAP+".alt");
+        assertEquals(2, mc.getAllCommands(MIMETYPE).length);
+       }
+
+}
diff --git 
a/activation-api-1.2.1/src/test/java/org/apache/servicemix/specs/activation/ITClearCurrentBundle.java
 
b/activation-api-1.2.1/src/test/java/org/apache/servicemix/specs/activation/ITClearCurrentBundle.java
new file mode 100644
index 0000000..7cf6f49
--- /dev/null
+++ 
b/activation-api-1.2.1/src/test/java/org/apache/servicemix/specs/activation/ITClearCurrentBundle.java
@@ -0,0 +1,75 @@
+/*
+ * 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.servicemix.specs.activation;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.net.URL;
+
+import javax.activation.CommandMap;
+import javax.activation.DataContentHandler;
+
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+
+/**
+ * After Activator.rebuildCommandMap the currentBundle of 
OsgiMailcapCommandMap should be null, so that calls
+ * to addMailcap do not register with the last started bundle.
+ */
+public class ITClearCurrentBundle {
+
+       @After
+       public void tearDown() {
+               CommandMap.setDefaultCommandMap(null);
+       }
+
+       @Test
+       public void testClearCurrentBundle() throws Exception {
+               Activator activator = new Activator();
+               Bundle bundle = 
createBundle(ITClearCurrentBundle.class.getResource("/mailcap.example"));
+               
+               activator.register(bundle);
+               
+               assertTrue(CommandMap.getDefaultCommandMap() instanceof 
OsgiMailcapCommandMap);
+               assertNullCurrentBundle((OsgiMailcapCommandMap) 
CommandMap.getDefaultCommandMap());
+       }
+
+       private void assertNullCurrentBundle(OsgiMailcapCommandMap commandMap) 
throws Exception {
+               Field field = 
OsgiMailcapCommandMap.class.getDeclaredField("currentBundle");
+               boolean oldAccessible = field.isAccessible();
+               try {
+                       field.setAccessible(true);
+                       assertNull(field.get(commandMap));
+               }
+               finally {
+                       field.setAccessible(oldAccessible);
+               }
+       }
+
+       private Bundle createBundle(URL mailcapResource) throws Exception {
+               Bundle result = Mockito.mock(Bundle.class);
+               
Mockito.when(result.loadClass("javax.activation.DataContentHandler")).thenReturn(DataContentHandler.class);
+               
Mockito.when(result.getResource("/META-INF/mailcap")).thenReturn(mailcapResource);
+               return result;
+       }
+}
diff --git a/activation-api-1.2.1/src/test/resources/mailcap.example 
b/activation-api-1.2.1/src/test/resources/mailcap.example
new file mode 100644
index 0000000..3ec1b0d
--- /dev/null
+++ b/activation-api-1.2.1/src/test/resources/mailcap.example
@@ -0,0 +1,2 @@
+# Example mailcap
+example/sm-4383;; x-java-content-handler=some.value

Reply via email to