You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2022/05/03 12:22:12 UTC

svn commit: r1900504 [4/22] - in /geronimo/specs/trunk: ./ geronimo-activation_2.0_spec/ geronimo-activation_2.0_spec/src/ geronimo-activation_2.0_spec/src/main/ geronimo-activation_2.0_spec/src/main/java/ geronimo-activation_2.0_spec/src/main/java/jak...

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/pom.xml?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/pom.xml (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/pom.xml Tue May  3 12:22:08 2022
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.geronimo.genesis</groupId>
+        <artifactId>genesis-java8-flava</artifactId>
+        <version>2.4</version>
+    </parent>
+
+    <groupId>org.apache.geronimo.specs</groupId>
+    <artifactId>geronimo-jakartamail_2.1_spec</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Geronimo Jakarta Mail Spec 2.1</name>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <description>Jakarta Mail 2.1 API Specification</description>
+
+    <url>http://geronimo.apache.org/maven/${siteId}/${project.version}</url>
+    <distributionManagement>
+        <site>
+            <id>apache-website</id>
+            <url>${site.deploy.url}/maven/${siteId}/${project.version}</url>
+        </site>
+    </distributionManagement>
+
+    <properties>
+        <siteId>specs/${project.artifactId}</siteId>
+        <geronimo.osgi.private.pkg>org.apache.geronimo.mail*</geronimo.osgi.private.pkg>
+        <geronimo.osgi.resources>src/main/resources/,META-INF/LICENSE.txt=LICENSE.txt,META-INF/NOTICE.txt=NOTICE.txt</geronimo.osgi.resources>
+    </properties>
+
+    <scm>
+        <connection>scm:svn:https://svn.apache.org/repos/asf/geronimo/specs/trunk/geronimo-javamail_2.1_spec</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/geronimo/specs/trunk/geronimo-javamail_2.1_spec</developerConnection>
+        <url>https://svn.apache.org/repos/asf/geronimo/specs/trunk/geronimo-javamail_2.1_spec</url>
+    </scm>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-activation_2.0_spec</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>4.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>4.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-osgi-locator</artifactId>
+            <version>1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-mime4j-core</artifactId>
+            <version>0.8.7</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.6.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>3.2.0</version>
+                <configuration>
+                    <doclint>none</doclint>  <!-- Turnoff all checks -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <configuration>
+                    <artifactSet>
+                        <includes>
+                            <include>org.apache.james:apache-mime4j-core</include>
+                        </includes>
+                    </artifactSet>
+                    <relocations>
+                        <relocation>
+                            <pattern>org.apache.james.mime4j</pattern>
+                            <shadedPattern>org.apache.geronimo.mail.james.mime4j</shadedPattern>
+                        </relocation>
+                    </relocations>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>3.5.0</version>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId};singleton=true</Bundle-SymbolicName>
+                        <Specification-Title>JSR-919 Jakarta Mail API 2.1</Specification-Title>
+                        <Specification-Vendor>The Eclipse Foundation</Specification-Vendor>
+                        <Specification-Version>2.1</Specification-Version>
+                        <Export-Package>jakarta.mail*;version=2.1,org.apache.geronimo.mail.util;version=2.1,org.apache.geronimo.mail.handlers;version=2.1</Export-Package>
+                        <Import-Package>org.apache.geronimo.osgi.registry.api;resolution:=optional,*</Import-Package>
+                        <Private-Package>org.apache.geronimo.osgi.locator,org.apache.geronimo.mail</Private-Package>
+                        <Bundle-Activator>org.apache.geronimo.mail.Activator</Bundle-Activator>
+                        <Provide-Capability><![CDATA[
+                           osgi.contract;osgi.contract=JakartaMail;uses:="${packages;NAMED;jakarta.*}";version:List<Version>='2.1'
+                        ]]></Provide-Capability>
+                        <_contract>JakartaActivation</_contract>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <profiles>
+        <profile>
+            <id>rat</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <!-- Override of default rat checks.  To use, type "mvn -Prat verify". -->
+                        <groupId>org.apache.rat</groupId>
+                        <artifactId>apache-rat-plugin</artifactId>
+                        <version>0.10</version>
+                        <executions>
+                            <execution>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <reportFile>${project.build.directory}/${project.build.finalName}.rat</reportFile>
+                            <excludeSubProjects>false</excludeSubProjects>
+                            <excludes>
+                                <exclude>**/target/**/*</exclude>
+                                <exclude>**/appended-resources/**/*</exclude>
+                                <exclude>**/velocity.log</exclude>
+                                <!-- manifest files don't support comments so don't contain the ASL2.0 header -->
+                                <exclude>**/*.MF</exclude>
+                                <!-- This is a test file that needs to be in exactly the format it is. -->
+                                <exclude>**/wmtom.bin</exclude>
+                                <!--RAT doesn't seem to recognize MIT style licenses-->
+                                <exclude>manual/src/styles/print.css</exclude>
+                            </excludes>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Address.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Address.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Address.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Address.java Tue May  3 12:22:08 2022
@@ -0,0 +1,55 @@
+/*
+ * 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 jakarta.mail;
+
+import java.io.Serializable;
+
+/**
+ * This abstract class models the addresses in a message.
+ * Addresses are Serializable so that they may be serialized along with other search terms.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class Address implements Serializable {
+
+     private static final long serialVersionUID = -5822459626751992278L;
+
+    /**
+     * Subclasses must provide a suitable implementation of equals().
+     *
+     * @param object the object to compare t
+     * @return true if the subclass determines the other object is equal to this Address
+     */
+    @Override
+    public abstract boolean equals(Object object);
+
+    /**
+     * Return a String that identifies this address type.
+     * @return the type of this address
+     */
+    public abstract String getType();
+
+    /**
+     * Subclasses must provide a suitable representation of their address.
+     * @return a representation of an Address as a String
+     */
+    @Override
+    public abstract String toString();
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/AuthenticationFailedException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/AuthenticationFailedException.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/AuthenticationFailedException.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/AuthenticationFailedException.java Tue May  3 12:22:08 2022
@@ -0,0 +1,50 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AuthenticationFailedException extends MessagingException {
+
+    private static final long serialVersionUID = 492080754054436511L;
+
+
+    public AuthenticationFailedException() {
+        super();
+    }
+
+    public AuthenticationFailedException(final String message) {
+        super(message);
+    }
+    
+    /**
+     * Constructs an AuthenticationFailedException with the specified
+     * detail message and embedded exception.  The exception is chained
+     * to this exception.
+     *
+     * @param message    The detailed error message
+     * @param e      The embedded exception
+     * @since        JavaMail 1.5
+     */
+    public AuthenticationFailedException(final String message, final Exception e) {
+        super(message, e);
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Authenticator.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Authenticator.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Authenticator.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Authenticator.java Tue May  3 12:22:08 2022
@@ -0,0 +1,66 @@
+/*
+ * 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 jakarta.mail;
+
+import java.net.InetAddress;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class Authenticator {
+    private InetAddress host;
+    private int port;
+    private String prompt;
+    private String protocol;
+    private String username;
+
+    synchronized PasswordAuthentication authenticate(final InetAddress host, final int port, final String protocol, final String prompt, final String username) {
+        this.host = host;
+        this.port = port;
+        this.protocol = protocol;
+        this.prompt = prompt;
+        this.username = username;
+        return getPasswordAuthentication();
+    }
+
+    protected final String getDefaultUserName() {
+        return username;
+    }
+
+    protected PasswordAuthentication getPasswordAuthentication() {
+        return null;
+    }
+
+    protected final int getRequestingPort() {
+        return port;
+    }
+
+    protected final String getRequestingPrompt() {
+        return prompt;
+    }
+
+    protected final String getRequestingProtocol() {
+        return protocol;
+    }
+
+    protected final InetAddress getRequestingSite() {
+        return host;
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/BodyPart.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/BodyPart.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/BodyPart.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/BodyPart.java Tue May  3 12:22:08 2022
@@ -0,0 +1,38 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class BodyPart implements Part {
+
+    protected Multipart parent;
+
+    public Multipart getParent() {
+        return parent;
+    }
+
+    // Can't be public. Not strictly required for spec, but mirrors Sun's javamail api impl.
+    void setParent(final Multipart parent)
+    {
+        this.parent = parent;
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EncodingAware.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EncodingAware.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EncodingAware.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EncodingAware.java Tue May  3 12:22:08 2022
@@ -0,0 +1,38 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * A class that implements EncodingAware may specify the Content-Transfer-Encoding
+ * to use for its data.  Valid Content-Transfer-Encoding values specified
+ * by RFC 2045 are "7bit", "8bit", "quoted-printable", "base64", and "binary".
+ * This is mainly used for {@link jakarta.activation.DataSource DataSource}s.
+ *
+ * @since   JavaMail 1.5
+ */
+
+public interface EncodingAware {
+
+    /**
+     * @return the MIME Content-Transfer-Encoding to use for this data,
+     * or null to indicate that an appropriate value should be chosen
+     * by the caller.
+     */
+    public String getEncoding();
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EventQueue.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EventQueue.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EventQueue.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/EventQueue.java Tue May  3 12:22:08 2022
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package jakarta.mail;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import jakarta.mail.event.MailEvent;
+
+/**
+ * This is an event queue to dispatch javamail events on separate threads
+ * from the main thread.  EventQueues are created by javamail Services 
+ * (Transport and Store instances), as well as Folders created from Store 
+ * instances.  Each entity will have its own private EventQueue instance, but 
+ * will delay creating it until it has an event to dispatch to a real listener.
+ * 
+ * NOTE:  It would be nice to use the concurrency support in Java 5 to 
+ * manage the queue, but this code needs to run on Java 1.4 still.  We also 
+ * don't want to have dependencies on other packages with this, so no 
+ * outside concurrency packages can be used either. 
+ * @version $Rev$ $Date$
+ */
+class EventQueue implements Runnable {
+    /**
+     * The dispatch thread that handles notification events. 
+     */
+    protected Thread dispatchThread; 
+    
+    /**
+     * The dispatching queue for events. 
+     */
+    protected List eventQueue = new LinkedList(); 
+    
+    /**
+     * Create a new EventQueue, including starting the new thread. 
+     */
+    public EventQueue() {
+        dispatchThread = new Thread(this, "JavaMail-EventQueue"); 
+        dispatchThread.setDaemon(true);  // this is a background server thread. 
+        // start the thread up 
+        dispatchThread.start(); 
+    }
+    
+    /**
+     * When an object implementing interface <code>Runnable</code> is used
+     * to create a thread, starting the thread causes the object's
+     * <code>run</code> method to be called in that separately executing
+     * thread.
+     * <p>
+     * The general contract of the method <code>run</code> is that it may
+     * take any action whatsoever.
+     *
+     * @see     java.lang.Thread#run()
+     */
+    public void run() {
+        try {
+            while (true) {
+                // get the next event 
+                final PendingEvent p = dequeueEvent(); 
+                // an empty event on the queue means time to shut things down. 
+                if (p.event == null) {
+                    return; 
+                }
+                
+                // and tap the listeners on the shoulder. 
+                dispatchEvent(p.event, p.listeners); 
+            }
+        } catch (final InterruptedException e) {
+            // been told to stop, so we stop 
+        }
+    }
+    
+    
+   /**
+    * Stop the EventQueue.  This will terminate the dispatcher thread as soon 
+    * as it can, so there may be undispatched events in the queue that will 
+    * not get dispatched. 
+    */
+    public synchronized void stop() {
+        // if the thread has not been stopped yet, interrupt it 
+        // and clear the reference. 
+        if (dispatchThread != null) {
+            // push a dummy marker on to the event queue  
+            // to force the dispatch thread to wake up. 
+            queueEvent(null, null); 
+            dispatchThread = null; 
+        }
+    }
+    
+    /**
+     * Add a new event to the queue.  
+     * 
+     * @param event     The event to dispatch.
+     * @param listeners The List of listeners to dispatch this to.  This is assumed to be a
+     *                  static snapshot of the listeners that will not change between the time
+     *                  the event is queued and the dispatcher thread makes the calls to the
+     *                  handlers.
+     */
+    public synchronized void queueEvent(final MailEvent event, final List listeners) {
+        // add an element to the list, then notify the processing thread. 
+        // Note that we make a copy of the listeners list.  This ensures 
+        // we're going to dispatch this to the snapshot of the listeners 
+        final PendingEvent p = new PendingEvent(event, listeners);
+        eventQueue.add(p);         
+        // wake up the dispatch thread 
+        notify(); 
+    }
+    
+    /**
+     * Remove the next event from the message queue. 
+     * 
+     * @return The PendingEvent item from the queue. 
+     */
+    protected synchronized PendingEvent dequeueEvent() throws InterruptedException {
+        // a little spin loop to wait for an event 
+        while (eventQueue.isEmpty()) {
+            wait(); 
+        }
+        
+        // just remove the first element of this 
+        return (PendingEvent)eventQueue.remove(0); 
+    }
+    
+    
+    /**
+     * Dispatch an event to a list of listeners.  Any exceptions thrown by 
+     * the listeners will be swallowed.
+     * 
+     * @param event     The event to dispatch.
+     * @param listeners The list of listeners this gets dispatched to.
+     */
+    protected void dispatchEvent(final MailEvent event, final List listeners) {
+        // iterate through the listeners list calling the handlers. 
+        for (int i = 0; i < listeners.size(); i++) {
+            try {
+                event.dispatch(listeners.get(i)); 
+            } catch (final Throwable e) {
+                // just eat these 
+            }
+        }
+    }
+        
+        
+    /**
+     * Small helper class to give a single reference handle for a pending event. 
+     */
+    class PendingEvent {
+        // the event we're broadcasting  
+        MailEvent event;  
+        // the list of listeners we send this to. 
+        List listeners; 
+            
+        PendingEvent(final MailEvent event, final List listeners) {    
+            this.event = event; 
+            this.listeners = listeners; 
+        }
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FetchProfile.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FetchProfile.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FetchProfile.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FetchProfile.java Tue May  3 12:22:08 2022
@@ -0,0 +1,135 @@
+/*
+ * 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 jakarta.mail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A FetchProfile defines a list of message attributes that a client wishes to prefetch
+ * from the server during a fetch operation.
+ *
+ * Clients can either specify individual headers, or can reference common profiles
+ * as defined by {@link FetchProfile.Item FetchProfile.Item}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FetchProfile {
+    /**
+     * Inner class that defines sets of headers that are commonly bundled together
+     * in a FetchProfile.
+     */
+    public static class Item {
+        /**
+         * Item for fetching information about the content of the message.
+         *
+         * This includes all the headers about the content including but not limited to:
+         * Content-Type, Content-Disposition, Content-Description, Size and Line-Count
+         */
+        public static final Item CONTENT_INFO = new Item("CONTENT_INFO");
+
+        /**
+         * Item for fetching information about the envelope of the message.
+         *
+         * This includes all the headers comprising the envelope including but not limited to:
+         * From, To, Cc, Bcc, Reply-To, Subject and Date
+         *
+         * For IMAP4, this should also include the ENVELOPE data item.
+         *
+         */
+        public static final Item ENVELOPE = new Item("ENVELOPE");
+
+        /**
+         * Item for fetching information about message flags.
+         * General corresponds to the X-Flags header.
+         */
+        public static final Item FLAGS = new Item("FLAGS");
+        
+        /**
+         * SIZE is a fetch profile item that can be included in a
+         * FetchProfile during a fetch request to a Folder.
+         * This item indicates that the sizes of the messages in the specified 
+         * range should be prefetched. 
+
+         *
+         * @since   JavaMail 1.5
+         */
+        public static final Item SIZE = new Item("SIZE");
+
+        protected Item(final String name) {
+            // hmmm, name is passed in but we are not allowed to provide accessors
+            // or to override equals/hashCode so what use is it?
+        }
+    }
+
+    // use Lists as we don't expect contains to be called often and the number of elements should be small
+    private final List items = new ArrayList();
+    private final List headers = new ArrayList();
+
+    /**
+     * Add a predefined profile of headers.
+     *
+     * @param item the profile to add
+     */
+    public void add(final Item item) {
+        items.add(item);
+    }
+
+    /**
+     * Add a specific header.
+     * @param header the header whose value should be prefetched
+     */
+    public void add(final String header) {
+        headers.add(header);
+    }
+
+    /**
+     * Determine if the given profile item is already included.
+     * @param item the profile to check for
+     * @return true if the profile item is already included
+     */
+    public boolean contains(final Item item) {
+        return items.contains(item);
+    }
+
+    /**
+     * Determine if the specified header is already included.
+     * @param header the header to check for
+     * @return true if the header is already included
+     */
+    public boolean contains(final String header) {
+        return headers.contains(header);
+    }
+
+    /**
+     * Get the profile items already included.
+     * @return the items already added to this profile
+     */
+    public Item[] getItems() {
+        return (Item[]) items.toArray(new Item[items.size()]);
+    }
+
+    /** Get the headers that have already been included.
+     * @return the headers already added to this profile
+     */
+    public String[] getHeaderNames() {
+        return (String[]) headers.toArray(new String[headers.size()]);
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Flags.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Flags.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Flags.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Flags.java Tue May  3 12:22:08 2022
@@ -0,0 +1,347 @@
+/*
+ * 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 jakarta.mail;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+/**
+ * Representation of flags that may be associated with a message.
+ * Flags can either be system flags, defined by the {@link Flags.Flag Flag} inner class,
+ * or user-defined flags defined by a String. The system flags represent those expected
+ * to be provided by most folder systems; user-defined flags allow for additional flags
+ * on a per-provider basis.
+ * <p/>
+ * This class is Serializable but compatibility is not guaranteed across releases.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Flags implements Cloneable, Serializable {
+
+    private static final long serialVersionUID = 6243590407214169028L;
+
+    public static final class Flag {
+        /**
+         * Flag that indicates that the message has been replied to; has a bit value of 1.
+         */
+        public static final Flag ANSWERED = new Flag(1);
+        /**
+         * Flag that indicates that the message has been marked for deletion and
+         * should be removed on a subsequent expunge operation; has a bit value of 2.
+         */
+        public static final Flag DELETED = new Flag(2);
+        /**
+         * Flag that indicates that the message is a draft; has a bit value of 4.
+         */
+        public static final Flag DRAFT = new Flag(4);
+        /**
+         * Flag that indicates that the message has been flagged; has a bit value of 8.
+         */
+        public static final Flag FLAGGED = new Flag(8);
+        /**
+         * Flag that indicates that the message has been delivered since the last time
+         * this folder was opened; has a bit value of 16.
+         */
+        public static final Flag RECENT = new Flag(16);
+        /**
+         * Flag that indicates that the message has been viewed; has a bit value of 32.
+         * This flag is set by the {@link Message#getInputStream()} and {@link Message#getContent()}
+         * methods.
+         */
+        public static final Flag SEEN = new Flag(32);
+        /**
+         * Flags that indicates if this folder supports user-defined flags; has a bit value of 0x80000000.
+         */
+        public static final Flag USER = new Flag(0x80000000);
+
+        private final int mask;
+
+        private Flag(final int mask) {
+            this.mask = mask;
+        }
+    }
+
+    // the Serialized form of this class required the following two fields to be persisted
+    // this leads to a specific type of implementation
+    private int system_flags;
+    private final Hashtable<String, String> user_flags;
+
+    /**
+     * Construct a Flags instance with no flags set.
+     */
+    public Flags() {
+        user_flags = new Hashtable<>();
+    }
+
+    /**
+     * Construct a Flags instance with a supplied system flag set.
+     * @param flag the system flag to set
+     */
+    public Flags(final Flag flag) {
+        system_flags = flag.mask;
+        user_flags = new Hashtable<>();
+    }
+
+    /**
+     * Construct a Flags instance with a same flags set.
+     * @param flags the instance to copy
+     */
+    public Flags(final Flags flags) {
+        system_flags = flags.system_flags;
+        user_flags = new Hashtable<>(flags.user_flags);
+    }
+
+    /**
+     * Construct a Flags instance with the supplied user flags set.
+     * Question: should this automatically set the USER system flag?
+     * @param name the user flag to set
+     */
+    public Flags(final String name) {
+        user_flags = new Hashtable<>();
+        user_flags.put(name.toLowerCase(), name);
+    }
+
+    /**
+     * Set a system flag.
+     * @param flag the system flag to set
+     */
+    public void add(final Flag flag) {
+        system_flags |= flag.mask;
+    }
+
+    /**
+     * Set all system and user flags from the supplied Flags.
+     * Question: do we need to check compatibility of USER flags?
+     * @param flags the Flags to add
+     */
+    public void add(final Flags flags) {
+        system_flags |= flags.system_flags;
+        user_flags.putAll(flags.user_flags);
+    }
+
+    /**
+     * Set a user flag.
+     * Question: should this fail if the USER system flag is not set?
+     * @param name the user flag to set
+     */
+    public void add(final String name) {
+        user_flags.put(name.toLowerCase(), name);
+    }
+
+    /**
+     * Return a copy of this instance.
+     * @return a copy of this instance
+     */
+    @Override
+    public Object clone() {
+        return new Flags(this);
+    }
+
+    /**
+     * See if the supplied system flags are set
+     * @param flag the system flags to check for
+     * @return true if the flags are set
+     */
+    public boolean contains(final Flag flag) {
+        return (system_flags & flag.mask) != 0;
+    }
+
+    /**
+     * See if all of the supplied Flags are set
+     * @param flags the flags to check for
+     * @return true if all the supplied system and user flags are set
+     */
+    public boolean contains(final Flags flags) {
+        return ((system_flags & flags.system_flags) == flags.system_flags)
+                && user_flags.keySet().containsAll(flags.user_flags.keySet());
+    }
+
+    /**
+     * See if the supplied user flag is set
+     * @param name the user flag to check for
+     * @return true if the flag is set
+     */
+    public boolean contains(final String name) {
+        return user_flags.containsKey(name.toLowerCase());
+    }
+
+    /**
+     * Equality is defined as true if the other object is a instanceof Flags with the
+     * same system and user flags set (using a case-insensitive name comparison for user flags).
+     * @param other the instance to compare against
+     * @return true if the two instance are the same
+     */
+    @Override
+    public boolean equals(final Object other) {
+        if (other == this) {
+			return true;
+		}
+        if (other instanceof Flags == false) {
+			return false;
+		}
+        final Flags flags = (Flags) other;
+        return system_flags == flags.system_flags && user_flags.keySet().equals(flags.user_flags.keySet());
+    }
+
+    /**
+     * Calculate a hashCode for this instance
+     * @return a hashCode for this instance
+     */
+    @Override
+    public int hashCode() {
+        return system_flags ^ user_flags.keySet().hashCode();
+    }
+
+    /**
+     * Return a list of {@link Flags.Flag Flags} containing the system flags that have been set
+     * @return the system flags that have been set
+     */
+    public Flag[] getSystemFlags() {
+        // assumption: it is quicker to calculate the size than it is to reallocate the array
+        int size = 0;
+        if ((system_flags & Flag.ANSWERED.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.DELETED.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.DRAFT.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.FLAGGED.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.RECENT.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.SEEN.mask) != 0) {
+			size += 1;
+		}
+        if ((system_flags & Flag.USER.mask) != 0) {
+			size += 1;
+		}
+        final Flag[] result = new Flag[size];
+        if ((system_flags & Flag.USER.mask) != 0) {
+			result[--size] = Flag.USER;
+		}
+        if ((system_flags & Flag.SEEN.mask) != 0) {
+			result[--size] = Flag.SEEN;
+		}
+        if ((system_flags & Flag.RECENT.mask) != 0) {
+			result[--size] = Flag.RECENT;
+		}
+        if ((system_flags & Flag.FLAGGED.mask) != 0) {
+			result[--size] = Flag.FLAGGED;
+		}
+        if ((system_flags & Flag.DRAFT.mask) != 0) {
+			result[--size] = Flag.DRAFT;
+		}
+        if ((system_flags & Flag.DELETED.mask) != 0) {
+			result[--size] = Flag.DELETED;
+		}
+        if ((system_flags & Flag.ANSWERED.mask) != 0) {
+			result[--size] = Flag.ANSWERED;
+		}
+        return result;
+    }
+
+    /**
+     * Return a list of user flags that have been set
+     * @return a list of user flags
+     */
+    public String[] getUserFlags() {
+        return (String[]) user_flags.values().toArray(new String[user_flags.values().size()]);
+    }
+
+    /**
+     * Unset the supplied system flag.
+     * Question: what happens if we unset the USER flags and user flags are set?
+     * @param flag the flag to clear
+     */
+    public void remove(final Flag flag) {
+        system_flags &= ~flag.mask;
+    }
+
+    /**
+     * Unset all flags from the supplied instance.
+     * @param flags the flags to clear
+     */
+    public void remove(final Flags flags) {
+        system_flags &= ~flags.system_flags;
+        user_flags.keySet().removeAll(flags.user_flags.keySet());
+    }
+
+    /**
+     * Unset the supplied user flag.
+     * @param name the flag to clear
+     */
+    public void remove(final String name) {
+        user_flags.remove(name.toLowerCase());
+    }
+
+    /**
+     * Remove any flags <strong>not</strong> in the given Flags object.
+     * Useful for clearing flags not supported by a server.  If the
+     * given Flags object includes the Flags.Flag.USER flag, all user
+     * flags in this Flags object are retained.
+     *
+     * @param	f	the flags to keep
+     * @return		true if this Flags object changed
+     * @since		JavaMail 1.6
+     */
+    public boolean retainAll(Flags f) {
+        boolean changed = false;
+
+        if (this.system_flags != f.system_flags) {
+            this.system_flags = f.system_flags;
+            changed = true;
+        }
+
+        final Set<String> keys = new HashSet<>(this.user_flags.keySet());
+        for (final String user_flag : keys) {
+            if (! f.user_flags.containsKey(user_flag)) {
+                this.user_flags.remove(user_flag);
+                changed = true;
+            }
+        }
+
+        return changed;
+    }
+
+    /**
+     * Clear all of the system flags.
+     *
+     * @since	JavaMail 1.6
+     */
+    public void clearSystemFlags() {
+        this.system_flags = 0;
+    }
+
+    /**
+     * Clear all of the user flags.
+     *
+     * @since	JavaMail 1.6
+     */
+    public void clearUserFlags() {
+        this.user_flags.clear();
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Folder.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Folder.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Folder.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Folder.java Tue May  3 12:22:08 2022
@@ -0,0 +1,773 @@
+/*
+ * 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 jakarta.mail;
+
+import jakarta.mail.search.SearchTerm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jakarta.mail.Flags.Flag;
+import jakarta.mail.event.ConnectionEvent;
+import jakarta.mail.event.ConnectionListener;
+import jakarta.mail.event.FolderEvent;
+import jakarta.mail.event.FolderListener;
+import jakarta.mail.event.MailEvent;
+import jakarta.mail.event.MessageChangedEvent;
+import jakarta.mail.event.MessageChangedListener;
+import jakarta.mail.event.MessageCountEvent;
+import jakarta.mail.event.MessageCountListener;
+
+/**
+ * An abstract representation of a folder in a mail system; subclasses would
+ * implement Folders for each supported protocol.
+ * <p/>
+ * Depending on protocol and implementation, folders may contain other folders, messages,
+ * or both as indicated by the {@link Folder#HOLDS_FOLDERS} and {@link Folder#HOLDS_MESSAGES} flags.
+ * If the immplementation supports hierarchical folders, the format of folder names is
+ * implementation dependent; however, components of the name are separated by the
+ * delimiter character returned by {@link Folder#getSeparator()}.
+ * <p/>
+ * The case-insensitive folder name "INBOX" is reserved to refer to the primary folder
+ * for the current user on the current server; not all stores will provide an INBOX
+ * and it may not be available at all times.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class Folder implements AutoCloseable {
+    /**
+     * Flag that indicates that a folder can contain messages.
+     */
+    public static final int HOLDS_MESSAGES = 1;
+    /**
+     * Flag that indicates that a folder can contain other folders.
+     */
+    public static final int HOLDS_FOLDERS = 2;
+
+    /**
+     * Flag indicating that this folder cannot be modified.
+     */
+    public static final int READ_ONLY = 1;
+    /**
+     * Flag indictaing that this folder can be modified.
+     * Question: what does it mean if both are set?
+     */
+    public static final int READ_WRITE = 2;
+
+    /**
+     * The store that this folder is part of.
+     */
+    protected Store store;
+    /**
+     * The current mode of this folder.
+     * When open, this can be {@link #READ_ONLY} or {@link #READ_WRITE};
+     * otherwise is set to -1.
+     */
+    protected int mode = -1;
+
+    private final ArrayList connectionListeners = new ArrayList(2);
+    private final ArrayList folderListeners = new ArrayList(2);
+    private final ArrayList messageChangedListeners = new ArrayList(2);
+    private final ArrayList messageCountListeners = new ArrayList(2);
+    // the EventQueue spins off a new thread, so we only create this 
+    // if we have actual listeners to dispatch an event to. 
+    private EventQueue queue = null;
+
+    /**
+     * Constructor that initializes the Store.
+     *
+     * @param store the store that this folder is part of
+     */
+    protected Folder(final Store store) {
+        this.store = store;
+    }
+
+    /**
+     * Return the name of this folder.
+     * This can be invoked when the folder is closed.
+     *
+     * @return this folder's name
+     */
+    public abstract String getName();
+
+    /**
+     * Return the full absolute name of this folder.
+     * This can be invoked when the folder is closed.
+     *
+     * @return the full name of this folder
+     */
+    public abstract String getFullName();
+
+    /**
+     * Return the URLName for this folder, which includes the location of the store.
+     *
+     * @return the URLName for this folder
+     * @throws MessagingException
+     */
+    public URLName getURLName() throws MessagingException {
+        final URLName baseURL = store.getURLName(); 
+        return new URLName(baseURL.getProtocol(), baseURL.getHost(), baseURL.getPort(), 
+            getFullName(), baseURL.getUsername(), null); 
+    }
+
+    /**
+     * Return the store that this folder is part of.
+     *
+     * @return the store this folder is part of
+     */
+    public Store getStore() {
+        return store;
+    }
+
+    /**
+     * Return the parent for this folder; if the folder is at the root of a heirarchy
+     * this returns null.
+     * This can be invoked when the folder is closed.
+     *
+     * @return this folder's parent
+     * @throws MessagingException
+     */
+    public abstract Folder getParent() throws MessagingException;
+
+    /**
+     * Check to see if this folder physically exists in the store.
+     * This can be invoked when the folder is closed.
+     *
+     * @return true if the folder really exists
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract boolean exists() throws MessagingException;
+
+    /**
+     * Return a list of folders from this Folder's namespace that match the supplied pattern.
+     * Patterns may contain the following wildcards:
+     * <ul><li>'%' which matches any characater except hierarchy delimiters</li>
+     * <li>'*' which matches any character including hierarchy delimiters</li>
+     * </ul>
+     * This can be invoked when the folder is closed.
+     *
+     * @param pattern the pattern to search for
+     * @return a, possibly empty, array containing Folders that matched the pattern
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract Folder[] list(String pattern) throws MessagingException;
+
+    /**
+     * Return a list of folders to which the user is subscribed and which match the supplied pattern.
+     * If the store does not support the concept of subscription then this should match against
+     * all folders; the default implementation of this method achieves this by defaulting to the
+     * {@link #list(String)} method.
+     *
+     * @param pattern the pattern to search for
+     * @return a, possibly empty, array containing subscribed Folders that matched the pattern
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Folder[] listSubscribed(final String pattern) throws MessagingException {
+        return list(pattern);
+    }
+
+    /**
+     * Convenience method that invokes {@link #list(String)} with the pattern "%".
+     *
+     * @return a, possibly empty, array of subfolders
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Folder[] list() throws MessagingException {
+        return list("%");
+    }
+
+    /**
+     * Convenience method that invokes {@link #listSubscribed(String)} with the pattern "%".
+     *
+     * @return a, possibly empty, array of subscribed subfolders
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Folder[] listSubscribed() throws MessagingException {
+        return listSubscribed("%");
+    }
+
+    /**
+     * Return the character used by this folder's Store to separate path components.
+     *
+     * @return the name separater character
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract char getSeparator() throws MessagingException;
+
+    /**
+     * Return the type of this folder, indicating whether it can contain subfolders,
+     * messages, or both. The value returned is a bitmask with the appropriate bits set.
+     *
+     * @return the type of this folder
+     * @throws MessagingException if there was a problem accessing the store
+     * @see #HOLDS_FOLDERS
+     * @see #HOLDS_MESSAGES
+     */
+    public abstract int getType() throws MessagingException;
+
+    /**
+     * Create a new folder capable of containing subfoldera and/or messages as
+     * determined by the type parameter. Any hierarchy defined by the folder
+     * name will be recursively created.
+     * If the folder was sucessfully created, a {@link FolderEvent#CREATED CREATED FolderEvent}
+     * is sent to all FolderListeners registered with this Folder or with the Store.
+     *
+     * @param type the type, indicating if this folder should contain subfolders, messages or both
+     * @return true if the folder was sucessfully created
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract boolean create(int type) throws MessagingException;
+
+    /**
+     * Determine if the user is subscribed to this Folder. The default implementation in
+     * this class always returns true.
+     *
+     * @return true is the user is subscribed to this Folder
+     */
+    public boolean isSubscribed() {
+        return true;
+    }
+
+    /**
+     * Set the user's subscription to this folder.
+     * Not all Stores support subscription; the default implementation in this class
+     * always throws a MethodNotSupportedException
+     *
+     * @param subscribed whether to subscribe to this Folder
+     * @throws MessagingException          if there was a problem accessing the store
+     * @throws MethodNotSupportedException if the Store does not support subscription
+     */
+    public void setSubscribed(final boolean subscribed) throws MessagingException {
+        throw new MethodNotSupportedException();
+    }
+
+    /**
+     * Check to see if this Folder conatins messages with the {@link Flag.RECENT} flag set.
+     * This can be used when the folder is closed to perform a light-weight check for new mail;
+     * to perform an incremental check for new mail the folder must be opened.
+     *
+     * @return true if the Store has recent messages
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract boolean hasNewMessages() throws MessagingException;
+
+    /**
+     * Get the Folder determined by the supplied name; if the name is relative
+     * then it is interpreted relative to this folder. This does not check that
+     * the named folder actually exists.
+     *
+     * @param name the name of the folder to return
+     * @return the named folder
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract Folder getFolder(String name) throws MessagingException;
+
+    /**
+     * Delete this folder and possibly any subfolders. This operation can only be
+     * performed on a closed folder.
+     * If recurse is true, then all subfolders are deleted first, then any messages in
+     * this folder are removed and it is finally deleted; {@link FolderEvent#DELETED}
+     * events are sent as appropriate.
+     * If recurse is false, then the behaviour depends on the folder type and store
+     * implementation as followd:
+     * <ul>
+     * <li>If the folder can only conrain messages, then all messages are removed and
+     * then the folder is deleted; a {@link FolderEvent#DELETED} event is sent.</li>
+     * <li>If the folder can onlu contain subfolders, then if it is empty it will be
+     * deleted and a {@link FolderEvent#DELETED} event is sent; if the folder is not
+     * empty then the delete fails and this method returns false.</li>
+     * <li>If the folder can contain both subfolders and messages, then if the folder
+     * does not contain any subfolders, any messages are deleted, the folder itself
+     * is deleted and a {@link FolderEvent#DELETED} event is sent; if the folder does
+     * contain subfolders then the implementation may choose from the following three
+     * behaviors:
+     * <ol>
+     * <li>it may return false indicting the operation failed</li>
+     * <li>it may remove all messages within the folder, send a {@link FolderEvent#DELETED}
+     * event, and then return true to indicate the delete was performed. Note this does
+     * not delete the folder itself and the {@link #exists()} operation for this folder
+     * will return true</li>
+     * <li>it may remove all messages within the folder as per the previous option; in
+     * addition it may change the type of the Folder to only HOLDS_FOLDERS indictaing
+     * that messages may no longer be added</li>
+     * </li>
+     * </ul>
+     * FolderEvents are sent to all listeners registered with this folder or
+     * with the Store.
+     *
+     * @param recurse whether subfolders should be recursively deleted as well
+     * @return true if the delete operation succeeds
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract boolean delete(boolean recurse) throws MessagingException;
+
+    /**
+     * Rename this folder; the folder must be closed.
+     * If the rename is successfull, a {@link FolderEvent#RENAMED} event is sent to
+     * all listeners registered with this folder or with the store.
+     *
+     * @param newName the new name for this folder
+     * @return true if the rename succeeded
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract boolean renameTo(Folder newName) throws MessagingException;
+
+    /**
+     * Open this folder; the folder must be able to contain messages and
+     * must currently be closed. If the folder is opened successfully then
+     * a {@link ConnectionEvent#OPENED} event is sent to listeners registered
+     * with this Folder.
+     * <p/>
+     * Whether the Store allows multiple connections or if it allows multiple
+     * writers is implementation defined.
+     *
+     * @param mode READ_ONLY or READ_WRITE
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract void open(int mode) throws MessagingException;
+
+    /**
+     * Close this folder; it must already be open.
+     * A {@link ConnectionEvent#CLOSED} event is sent to all listeners registered
+     * with this folder.
+     *
+     * @param expunge whether to expunge all deleted messages
+     * @throws MessagingException if there was a problem accessing the store; the folder is still closed
+     */
+    public abstract void close(boolean expunge) throws MessagingException;
+
+    /**
+     * Indicates that the folder has been opened.
+     *
+     * @return true if the folder is open
+     */
+    public abstract boolean isOpen();
+
+    /**
+     * Return the mode of this folder ass passed to {@link #open(int)}, or -1 if
+     * the folder is closed.
+     *
+     * @return the mode this folder was opened with
+     */
+    public int getMode() {
+        return mode;
+    }
+
+    /**
+     * Get the flags supported by this folder.
+     *
+     * @return the flags supported by this folder, or null if unknown
+     * @see Flags
+     */
+    public abstract Flags getPermanentFlags();
+
+    /**
+     * Return the number of messages this folder contains.
+     * If this operation is invoked on a closed folder, the implementation
+     * may choose to return -1 to avoid the expense of opening the folder.
+     *
+     * @return the number of messages, or -1 if unknown
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract int getMessageCount() throws MessagingException;
+
+    /**
+     * Return the numbew of messages in this folder that have the {@link Flag.RECENT} flag set.
+     * If this operation is invoked on a closed folder, the implementation
+     * may choose to return -1 to avoid the expense of opening the folder.
+     * The default implmentation of this method iterates over all messages
+     * in the folder; subclasses should override if possible to provide a more
+     * efficient implementation.
+     *
+     * @return the number of new messages, or -1 if unknown
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public int getNewMessageCount() throws MessagingException {
+        return getCount(Flags.Flag.RECENT, true);
+    }
+
+    /**
+     * Return the numbew of messages in this folder that do not have the {@link Flag.SEEN} flag set.
+     * If this operation is invoked on a closed folder, the implementation
+     * may choose to return -1 to avoid the expense of opening the folder.
+     * The default implmentation of this method iterates over all messages
+     * in the folder; subclasses should override if possible to provide a more
+     * efficient implementation.
+     *
+     * @return the number of new messages, or -1 if unknown
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public int getUnreadMessageCount() throws MessagingException {
+        return getCount(Flags.Flag.SEEN, false);
+    }
+
+    /**
+     * Return the numbew of messages in this folder that have the {@link Flag.DELETED} flag set.
+     * If this operation is invoked on a closed folder, the implementation
+     * may choose to return -1 to avoid the expense of opening the folder.
+     * The default implmentation of this method iterates over all messages
+     * in the folder; subclasses should override if possible to provide a more
+     * efficient implementation.
+     *
+     * @return the number of new messages, or -1 if unknown
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public int getDeletedMessageCount() throws MessagingException {
+        return getCount(Flags.Flag.DELETED, true);
+    }
+
+    private int getCount(final Flag flag, final boolean value) throws MessagingException {
+        if (!isOpen()) {
+            return -1;
+        }
+        final Message[] messages = getMessages();
+        int total = 0;
+        for (int i = 0; i < messages.length; i++) {
+            if (messages[i].getFlags().contains(flag) == value) {
+                total++;
+            }
+        }
+        return total;
+    }
+
+    /**
+     * Retrieve the message with the specified index in this Folder;
+     * messages indices start at 1 not zero.
+     * Clients should note that the index for a specific message may change
+     * if the folder is expunged; {@link Message} objects should be used as
+     * references instead.
+     *
+     * @param index the index of the message to fetch
+     * @return the message
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract Message getMessage(int index) throws MessagingException;
+
+    /**
+     * Retrieve messages with index between start and end inclusive
+     *
+     * @param start index of first message
+     * @param end   index of last message
+     * @return an array of messages from start to end inclusive
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Message[] getMessages(int start, final int end) throws MessagingException {
+        final Message[] result = new Message[end - start + 1];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = getMessage(start++);
+        }
+        return result;
+    }
+
+    /**
+     * Retrieve messages with the specified indices.
+     *
+     * @param ids the indices of the messages to fetch
+     * @return the specified messages
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Message[] getMessages(final int ids[]) throws MessagingException {
+        final Message[] result = new Message[ids.length];
+        for (int i = 0; i < ids.length; i++) {
+            result[i] = getMessage(ids[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Retrieve all messages.
+     *
+     * @return all messages in this folder
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Message[] getMessages() throws MessagingException {
+        return getMessages(1, getMessageCount());
+    }
+
+    /**
+     * Append the supplied messages to this folder. A {@link MessageCountEvent} is sent
+     * to all listeners registered with this folder when all messages have been appended.
+     * If the array contains a previously expunged message, it must be re-appended to the Store
+     * and implementations must not abort this operation.
+     *
+     * @param messages the messages to append
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract void appendMessages(Message[] messages) throws MessagingException;
+
+    /**
+     * Hint to the store to prefetch information on the supplied messaged.
+     * Subclasses should override this method to provide an efficient implementation;
+     * the default implementation in this class simply returns.
+     *
+     * @param messages messages for which information should be fetched
+     * @param profile  the information to fetch
+     * @throws MessagingException if there was a problem accessing the store
+     * @see FetchProfile
+     */
+    public void fetch(final Message[] messages, final FetchProfile profile) throws MessagingException {
+        return;
+    }
+
+    /**
+     * Set flags on the messages to the supplied value; all messages must belong to this folder.
+     * This method may be overridden by subclasses that can optimize the setting
+     * of flags on multiple messages at once; the default implementation simply calls
+     * {@link Message#setFlags(Flags, boolean)} for each supplied messages.
+     *
+     * @param messages whose flags should be set
+     * @param flags    the set of flags to modify
+     * @param value    the value the flags should be set to
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public void setFlags(final Message[] messages, final Flags flags, final boolean value) throws MessagingException {
+        for (int i = 0; i < messages.length; i++) {
+            final Message message = messages[i];
+            message.setFlags(flags, value);
+        }
+    }
+
+    /**
+     * Set flags on a range of messages to the supplied value.
+     * This method may be overridden by subclasses that can optimize the setting
+     * of flags on multiple messages at once; the default implementation simply
+     * gets each message and then calls {@link Message#setFlags(Flags, boolean)}.
+     *
+     * @param start first message end set
+     * @param end   last message end set
+     * @param flags the set of flags end modify
+     * @param value the value the flags should be set end
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public void setFlags(final int start, final int end, final Flags flags, final boolean value) throws MessagingException {
+        for (int i = start; i <= end; i++) {
+            final Message message = getMessage(i);
+            message.setFlags(flags, value);
+        }
+    }
+
+    /**
+     * Set flags on a set of messages to the supplied value.
+     * This method may be overridden by subclasses that can optimize the setting
+     * of flags on multiple messages at once; the default implementation simply
+     * gets each message and then calls {@link Message#setFlags(Flags, boolean)}.
+     *
+     * @param ids   the indexes of the messages to set
+     * @param flags the set of flags end modify
+     * @param value the value the flags should be set end
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public void setFlags(final int ids[], final Flags flags, final boolean value) throws MessagingException {
+        for (int i = 0; i < ids.length; i++) {
+            final Message message = getMessage(ids[i]);
+            message.setFlags(flags, value);
+        }
+    }
+
+    /**
+     * Copy the specified messages to another folder.
+     * The default implementation simply appends the supplied messages to the
+     * target folder using {@link #appendMessages(Message[])}.
+     * @param messages the messages to copy
+     * @param folder the folder to copy to
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public void copyMessages(final Message[] messages, final Folder folder) throws MessagingException {
+        folder.appendMessages(messages);
+    }
+
+    /**
+     * Permanently delete all supplied messages that have the DELETED flag set from the Store.
+     * The original message indices of all messages actually deleted are returned and a
+     * {@link MessageCountEvent} event is sent to all listeners with this folder. The expunge
+     * may cause the indices of all messaged that remain in the folder to change.
+     *
+     * @return the original indices of messages that were actually deleted
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public abstract Message[] expunge() throws MessagingException;
+
+    /**
+     * Search this folder for messages matching the supplied search criteria.
+     * The default implementation simply invoke <code>search(term, getMessages())
+     * applying the search over all messages in the folder; subclasses may provide
+     * a more efficient mechanism.
+     *
+     * @param term the search criteria
+     * @return an array containing messages that match the criteria
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Message[] search(final SearchTerm term) throws MessagingException {
+        return search(term, getMessages());
+    }
+
+    /**
+     * Search the supplied messages for those that match the supplied criteria;
+     * messages must belong to this folder.
+     * The default implementation iterates through the messages, returning those
+     * whose {@link Message#match(SearchTerm)} method returns true;
+     * subclasses may provide a more efficient implementation.
+     *
+     * @param term the search criteria
+     * @param messages the messages to search
+     * @return an array containing messages that match the criteria
+     * @throws MessagingException if there was a problem accessing the store
+     */
+    public Message[] search(final SearchTerm term, final Message[] messages) throws MessagingException {
+        final List result = new ArrayList(messages.length);
+        for (int i = 0; i < messages.length; i++) {
+            final Message message = messages[i];
+            if (message.match(term)) {
+                result.add(message);
+            }
+        }
+        return (Message[]) result.toArray(new Message[result.size()]);
+    }
+
+    public void addConnectionListener(final ConnectionListener listener) {
+        connectionListeners.add(listener);
+    }
+
+    public void removeConnectionListener(final ConnectionListener listener) {
+        connectionListeners.remove(listener);
+    }
+
+    protected void notifyConnectionListeners(final int type) {
+        queueEvent(new ConnectionEvent(this, type), connectionListeners);
+    }
+
+    public void addFolderListener(final FolderListener listener) {
+        folderListeners.add(listener);
+    }
+
+    public void removeFolderListener(final FolderListener listener) {
+        folderListeners.remove(listener);
+    }
+
+    protected void notifyFolderListeners(final int type) {
+        queueEvent(new FolderEvent(this, this, type), folderListeners);
+    }
+
+    protected void notifyFolderRenamedListeners(final Folder newFolder) {
+        queueEvent(new FolderEvent(this, this, newFolder, FolderEvent.RENAMED), folderListeners);
+    }
+
+    public void addMessageCountListener(final MessageCountListener listener) {
+        messageCountListeners.add(listener);
+    }
+
+    public void removeMessageCountListener(final MessageCountListener listener) {
+        messageCountListeners.remove(listener);
+    }
+
+    protected void notifyMessageAddedListeners(final Message[] messages) {
+        queueEvent(new MessageCountEvent(this, MessageCountEvent.ADDED, false, messages), messageChangedListeners);
+    }
+
+    protected void notifyMessageRemovedListeners(final boolean removed, final Message[] messages) {
+        queueEvent(new MessageCountEvent(this, MessageCountEvent.REMOVED, removed, messages), messageChangedListeners);
+    }
+
+    public void addMessageChangedListener(final MessageChangedListener listener) {
+        messageChangedListeners.add(listener);
+    }
+
+    public void removeMessageChangedListener(final MessageChangedListener listener) {
+        messageChangedListeners.remove(listener);
+    }
+
+    protected void notifyMessageChangedListeners(final int type, final Message message) {
+        queueEvent(new MessageChangedEvent(this, type, message), messageChangedListeners);
+    }
+
+    /**
+     * Unregisters all listeners.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        // shut our queue down, if needed. 
+        if (queue != null) {
+            queue.stop();
+            queue = null; 
+        }
+        connectionListeners.clear();
+        folderListeners.clear();
+        messageChangedListeners.clear();
+        messageCountListeners.clear();
+        store = null;
+        super.finalize();
+    }
+
+    /**
+     * Returns the full name of this folder; if null, returns the value from the superclass.
+     * @return a string form of this folder
+     */
+    @Override
+    public String toString() {
+        final String name = getFullName();
+        return name == null ? super.toString() : name;
+    }
+    
+    
+    /**
+     * Add an event on the event queue, creating the queue if this is the 
+     * first event with actual listeners. 
+     * 
+     * @param event     The event to dispatch.
+     * @param listeners The listener list.
+     */
+    private synchronized void queueEvent(final MailEvent event, final ArrayList listeners) {
+        // if there are no listeners to dispatch this to, don't put it on the queue. 
+        // This allows us to delay creating the queue (and its new thread) until 
+        // we 
+        if (listeners.isEmpty()) {
+            return; 
+        }
+        // first real event?  Time to get the queue kicked off. 
+        if (queue == null) {
+            queue = new EventQueue(); 
+        }
+        // tee it up and let it rip. 
+        queue.queueEvent(event, (List)listeners.clone()); 
+    }
+
+    /**
+     * Close this Folder and expunge deleted messages. <p>
+     *
+     * A CLOSED ConnectionEvent is delivered to any ConnectionListeners
+     * registered on this Folder. Note that the folder is closed even
+     * if this method terminates abnormally by throwing a
+     * MessagingException. <p>
+     *
+     * This method supports the {@link java.lang.AutoCloseable AutoCloseable}
+     * interface. <p>
+     *
+     * This implementation calls <code>close(true)</code>.
+     *
+     * @exception	IllegalStateException if this folder is not opened
+     * @exception       MessagingException for other failures
+     * @see        ConnectionEvent
+     * @since		JavaMail 1.6
+     */
+    @Override
+    public void close() throws MessagingException {
+        close(true);
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderClosedException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderClosedException.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderClosedException.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderClosedException.java Tue May  3 12:22:08 2022
@@ -0,0 +1,60 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class FolderClosedException extends MessagingException {
+	
+	private static final long serialVersionUID = 1687879213433302315L;
+
+	
+    private transient Folder _folder;
+
+    public FolderClosedException(final Folder folder) {
+        this(folder, "Folder Closed: " + folder.getName());
+    }
+
+    public FolderClosedException(final Folder folder, final String message) {
+        super(message);
+        _folder = folder;
+    }
+    
+    /**
+     * Constructs a FolderClosedException with the specified
+     * detail message and embedded exception.  The exception is chained
+     * to this exception.
+     *
+     * @param folder     The Folder
+     * @param message    The detailed error message
+     * @param e      The embedded exception
+     * @since        JavaMail 1.5
+     */
+    public FolderClosedException(final Folder folder, final String message, final Exception e) {
+        super(message, e);
+        _folder = folder;
+    }
+    
+
+    public Folder getFolder() {
+        return _folder;
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderNotFoundException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderNotFoundException.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderNotFoundException.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/FolderNotFoundException.java Tue May  3 12:22:08 2022
@@ -0,0 +1,66 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class FolderNotFoundException extends MessagingException {
+	
+	private static final long serialVersionUID = 472612108891249403L;
+	
+    private transient Folder _folder;
+
+    public FolderNotFoundException() {
+        super();
+    }
+
+    public FolderNotFoundException(final Folder folder) {
+        this(folder, "Folder not found: " + folder.getName());
+    }
+
+    public FolderNotFoundException(final Folder folder, final String message) {
+        super(message);
+        _folder = folder;
+    }
+
+    public FolderNotFoundException(final String message, final Folder folder) {
+        this(folder, message);
+    }
+    
+    /**
+     * Constructs a FolderNotFoundException with the specified
+     * detail message and embedded exception.  The exception is chained
+     * to this exception.
+     *
+     * @param folder The Folder
+     * @param s      The detailed error message
+     * @param e      The embedded exception
+     * @since        JavaMail 1.5
+     */
+    public FolderNotFoundException(final Folder folder, final String s, final Exception e) {
+        super(s, e);
+        _folder = folder;
+    }
+
+    public Folder getFolder() {
+        return _folder;
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Header.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Header.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Header.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/Header.java Tue May  3 12:22:08 2022
@@ -0,0 +1,65 @@
+/*
+ * 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 jakarta.mail;
+
+/**
+ * Class representing a header field.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Header {
+    /**
+     * The name of the header.
+     */
+    protected String name;
+    /**
+     * The header value (can be null).
+     */
+    protected String value;
+
+    /**
+     * Constructor initializing all immutable fields.
+     *
+     * @param name  the name of this header
+     * @param value the value of this header
+     */
+    public Header(final String name, final String value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    /**
+     * Return the name of this header.
+     *
+     * @return the name of this header
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Return the value of this header.
+     *
+     * @return the value of this header
+     */
+    public String getValue() {
+        return value;
+    }
+}

Added: geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/IllegalWriteException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/IllegalWriteException.java?rev=1900504&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/IllegalWriteException.java (added)
+++ geronimo/specs/trunk/geronimo-jakartamail_2.1_spec/src/main/java/jakarta/mail/IllegalWriteException.java Tue May  3 12:22:08 2022
@@ -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 jakarta.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class IllegalWriteException extends MessagingException {
+	
+	private static final long serialVersionUID = 3974370223328268013L;
+	
+    public IllegalWriteException() {
+        super();
+    }
+
+    public IllegalWriteException(final String message) {
+        super(message);
+    }
+    
+    /**
+     * Constructs an IllegalWriteException with the specified
+     * detail message and embedded exception.  The exception is chained
+     * to this exception.
+     *
+     * @param s      The detailed error message
+     * @param e      The embedded exception
+     * @since        JavaMail 1.5
+     */
+    public IllegalWriteException(final String s, final Exception e) {
+        super(s, e);
+    }
+}