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 2019/09/04 16:45:50 UTC
svn commit: r1866401 [4/18] - in
/geronimo/specs/trunk/geronimo-javamail_1.6_spec: ./ .idea/
.idea/copyright/ .idea/libraries/ src/ src/main/ src/main/java/
src/main/java/javax/ src/main/java/javax/mail/
src/main/java/javax/mail/event/ src/main/java/ja...
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Part.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Part.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Part.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Part.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,316 @@
+/*
+ * 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.mail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+
+import javax.activation.DataHandler;
+
+/**
+ * Note: Parts are used in Collections so implementing classes must provide
+ * a suitable implementation of equals and hashCode.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Part {
+ /**
+ * This part should be presented as an attachment.
+ */
+ public static final String ATTACHMENT = "attachment";
+ /**
+ * This part should be presented or rendered inline.
+ */
+ public static final String INLINE = "inline";
+
+ /**
+ * Add this value to the existing headers with the given name. This method
+ * does not replace any headers that may already exist.
+ *
+ * @param name The name of the target header.
+ * @param value The value to be added to the header set.
+ *
+ * @exception MessagingException
+ */
+ public abstract void addHeader(String name, String value) throws MessagingException;
+
+ /**
+ * Return all headers as an Enumeration of Header objects.
+ *
+ * @return An Enumeration containing all of the current Header objects.
+ * @exception MessagingException
+ */
+ public abstract Enumeration getAllHeaders() throws MessagingException;
+
+ /**
+ * Return a content object for this Part. The
+ * content object type is dependent upon the
+ * DataHandler for the Part.
+ *
+ * @return A content object for this Part.
+ * @exception IOException
+ * @exception MessagingException
+ */
+ public abstract Object getContent() throws IOException, MessagingException;
+
+ /**
+ * Get the ContentType for this part, or null if the
+ * ContentType has not been set. The ContentType
+ * is expressed using the MIME typing system.
+ *
+ * @return The ContentType for this part.
+ * @exception MessagingException
+ */
+ public abstract String getContentType() throws MessagingException;
+
+ /**
+ * Returns a DataHandler instance for the content
+ * with in the Part.
+ *
+ * @return A DataHandler appropriate for the Part content.
+ * @exception MessagingException
+ */
+ public abstract DataHandler getDataHandler() throws MessagingException;
+
+ /**
+ * Returns a description string for this Part. Returns
+ * null if a description has not been set.
+ *
+ * @return The description string.
+ * @exception MessagingException
+ */
+ public abstract String getDescription() throws MessagingException;
+
+ /**
+ * Return the disposition of the part. The disposition
+ * determines how the part should be presented to the
+ * user. Two common disposition values are ATTACHMENT
+ * and INLINE.
+ *
+ * @return The current disposition value.
+ * @exception MessagingException
+ */
+ public abstract String getDisposition() throws MessagingException;
+
+ /**
+ * Get a file name associated with this part. The
+ * file name is useful for presenting attachment
+ * parts as their original source. The file names
+ * are generally simple names without containing
+ * any directory information. Returns null if the
+ * filename has not been set.
+ *
+ * @return The string filename, if any.
+ * @exception MessagingException
+ */
+ public abstract String getFileName() throws MessagingException;
+
+ /**
+ * Get all Headers for this header name. Returns null if no headers with
+ * the given name exist.
+ *
+ * @param name The target header name.
+ *
+ * @return An array of all matching header values, or null if the given header
+ * does not exist.
+ * @exception MessagingException
+ */
+ public abstract String[] getHeader(String name) throws MessagingException;
+
+ /**
+ * Return an InputStream for accessing the Part
+ * content. Any mail-related transfer encodings
+ * will be removed, so the data presented with
+ * be the actual part content.
+ *
+ * @return An InputStream for accessing the part content.
+ * @exception IOException
+ * @exception MessagingException
+ */
+ public abstract InputStream getInputStream() throws IOException, MessagingException;
+
+ /**
+ * Return the number of lines in the content, or
+ * -1 if the line count cannot be determined.
+ *
+ * @return The estimated number of lines in the content.
+ * @exception MessagingException
+ */
+ public abstract int getLineCount() throws MessagingException;
+
+ /**
+ * Return all headers that match the list of names as an Enumeration of
+ * Header objects.
+ *
+ * @param names An array of names of the desired headers.
+ *
+ * @return An Enumeration of Header objects containing the matching headers.
+ * @exception MessagingException
+ */
+ public abstract Enumeration getMatchingHeaders(String[] names) throws MessagingException;
+
+ /**
+ * Return an Enumeration of all Headers except those that match the names
+ * given in the exclusion list.
+ *
+ * @param names An array of String header names that will be excluded from the return
+ * Enumeration set.
+ *
+ * @return An Enumeration of Headers containing all headers except for those named
+ * in the exclusion list.
+ * @exception MessagingException
+ */
+ public abstract Enumeration getNonMatchingHeaders(String[] names) throws MessagingException;
+
+ /**
+ * Return the size of this part, or -1 if the size
+ * cannot be reliably determined.
+ *
+ * Note: the returned size does not take into account
+ * internal encodings, nor is it an estimate of
+ * how many bytes are required to transfer this
+ * part across a network. This value is intended
+ * to give email clients a rough idea of the amount
+ * of space that might be required to present the
+ * item.
+ *
+ * @return The estimated part size, or -1 if the size
+ * information cannot be determined.
+ * @exception MessagingException
+ */
+ public abstract int getSize() throws MessagingException;
+
+ /**
+ * Tests if the part is of the specified MIME type.
+ * Only the primaryPart and subPart of the MIME
+ * type are used for the comparison; arguments are
+ * ignored. The wildcard value of "*" may be used
+ * to match all subTypes.
+ *
+ * @param mimeType The target MIME type.
+ *
+ * @return true if the part matches the input MIME type,
+ * false if it is not of the requested type.
+ * @exception MessagingException
+ */
+ public abstract boolean isMimeType(String mimeType) throws MessagingException;
+
+ /**
+ * Remove all headers with the given name from the Part.
+ *
+ * @param name The target header name used for removal.
+ *
+ * @exception MessagingException
+ */
+ public abstract void removeHeader(String name) throws MessagingException;
+
+ public abstract void setContent(Multipart content) throws MessagingException;
+
+ /**
+ * Set a content object for this part. Internally,
+ * the Part will use the MIME type encoded in the
+ * type argument to wrap the provided content object.
+ * In order for this to work properly, an appropriate
+ * DataHandler must be installed in the Java Activation
+ * Framework.
+ *
+ * @param content The content object.
+ * @param type The MIME type for the inserted content Object.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setContent(Object content, String type) throws MessagingException;
+
+ /**
+ * Set a DataHandler for this part that defines the
+ * Part content. The DataHandler is used to access
+ * all Part content.
+ *
+ * @param handler The DataHandler instance.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setDataHandler(DataHandler handler) throws MessagingException;
+
+ /**
+ * Set a descriptive string for this part.
+ *
+ * @param description
+ * The new description.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setDescription(String description) throws MessagingException;
+
+ /**
+ * Set the disposition for this Part.
+ *
+ * @param disposition
+ * The disposition string.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setDisposition(String disposition) throws MessagingException;
+
+ /**
+ * Set a descriptive file name for this part. The
+ * name should be a simple name that does not include
+ * directory information.
+ *
+ * @param name The new name value.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setFileName(String name) throws MessagingException;
+
+ /**
+ * Sets a value for the given header. This operation will replace all
+ * existing headers with the given name.
+ *
+ * @param name The name of the target header.
+ * @param value The new value for the indicated header.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setHeader(String name, String value) throws MessagingException;
+
+ /**
+ * Set the Part content as text. This is a convenience method that sets
+ * the content to a MIME type of "text/plain".
+ *
+ * @param content The new text content, as a String object.
+ *
+ * @exception MessagingException
+ */
+ public abstract void setText(String content) throws MessagingException;
+
+ /**
+ * Write the Part content out to the provided OutputStream as a byte
+ * stream using an encoding appropriate to the Part content.
+ *
+ * @param out The target OutputStream.
+ *
+ * @exception IOException
+ * @exception MessagingException
+ */
+ public abstract void writeTo(OutputStream out) throws IOException, MessagingException;
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/PasswordAuthentication.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/PasswordAuthentication.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/PasswordAuthentication.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/PasswordAuthentication.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,43 @@
+/*
+ * 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.mail;
+
+/**
+ * A data holder used by Authenticator to contain a username and password.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class PasswordAuthentication {
+ private final String user;
+ private final String password;
+
+ public PasswordAuthentication(final String user, final String password) {
+ this.user = user;
+ this.password = password;
+ }
+
+ public String getUserName() {
+ return user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Provider.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Provider.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Provider.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Provider.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,89 @@
+/*
+ * 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.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class Provider {
+ /**
+ * A enumeration inner class that defines Provider types.
+ */
+ public static class Type {
+ /**
+ * A message store provider such as POP3 or IMAP4.
+ */
+ public static final Type STORE = new Type();
+
+ /**
+ * A message transport provider such as SMTP.
+ */
+ public static final Type TRANSPORT = new Type();
+
+ private Type() {
+ }
+ }
+
+ private final String className;
+ private final String protocol;
+ private final Type type;
+ private final String vendor;
+ private final String version;
+
+ public Provider(final Type type, final String protocol, final String className, final String vendor, final String version) {
+ this.protocol = protocol;
+ this.className = className;
+ this.type = type;
+ this.vendor = vendor;
+ this.version = version;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public String getVendor() {
+ return vendor;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ @Override
+ public String toString() {
+ return "protocol="
+ + protocol
+ + "; type="
+ + type
+ + "; class="
+ + className
+ + (vendor == null ? "" : "; vendor=" + vendor)
+ + (version == null ? "" : ";version=" + version);
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Quota.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Quota.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Quota.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Quota.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,128 @@
+/*
+ * 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.mail;
+
+/**
+ * A representation of a Quota item for a given quota root.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Quota {
+ /**
+ * The name of the quota root.
+ */
+ public String quotaRoot;
+
+ /**
+ * The resources associated with this quota root.
+ */
+ public Resource[] resources;
+
+
+ /**
+ * Create a Quota with the given name and no resources.
+ *
+ * @param quotaRoot The quota root name.
+ */
+ public Quota(final String quotaRoot) {
+ this.quotaRoot = quotaRoot;
+ }
+
+ /**
+ * Set a limit value for a resource. If the resource is not
+ * currently associated with this Quota, a new Resource item is
+ * added to the resources list.
+ *
+ * @param name The target resource name.
+ * @param limit The new limit value for the resource.
+ */
+ public void setResourceLimit(final String name, final long limit) {
+ final Resource target = findResource(name);
+ target.limit = limit;
+ }
+
+ /**
+ * Locate a particular named resource, adding one to the list
+ * if it does not exist.
+ *
+ * @param name The target resource name.
+ *
+ * @return A Resource item for this named resource (either existing or new).
+ */
+ private Resource findResource(final String name) {
+ // no resources yet? Make it so.
+ if (resources == null) {
+ final Resource target = new Resource(name, 0, 0);
+ resources = new Resource[] { target };
+ return target;
+ }
+
+ // see if this one exists and return it.
+ for (int i = 0; i < resources.length; i++) {
+ final Resource current = resources[i];
+ if (current.name.equalsIgnoreCase(name)) {
+ return current;
+ }
+ }
+
+ // have to extend the array...this is a pain.
+ final Resource[] newResources = new Resource[resources.length + 1];
+ System.arraycopy(resources, 0, newResources, 0, resources.length);
+ final Resource target = new Resource(name, 0, 0);
+ newResources[resources.length] = target;
+ resources = newResources;
+ return target;
+ }
+
+
+
+ /**
+ * A representation of a given resource definition.
+ */
+ public static class Resource {
+ /**
+ * The resource name.
+ */
+ public String name;
+ /**
+ * The current resource usage.
+ */
+ public long usage;
+ /**
+ * The limit value for this resource.
+ */
+ public long limit;
+
+
+ /**
+ * Construct a Resource object from the given name and usage/limit
+ * information.
+ *
+ * @param name The Resource name.
+ * @param usage The current resource usage.
+ * @param limit The Resource limit value.
+ */
+ public Resource(final String name, final long usage, final long limit) {
+ this.name = name;
+ this.usage = usage;
+ this.limit = limit;
+ }
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/QuotaAwareStore.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/QuotaAwareStore.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/QuotaAwareStore.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/QuotaAwareStore.java Wed Sep 4 16:45:48 2019
@@ -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.mail;
+
+/**
+ * An interface for Store implementations to support the IMAP RFC 2087 Quota extension.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface QuotaAwareStore {
+
+ /**
+ * Get the quotas for the specified root element.
+ *
+ * @param root The root name for the quota information.
+ *
+ * @return An array of Quota objects defined for the root.
+ * @throws MessagingException if the quotas cannot be retrieved
+ */
+ public Quota[] getQuota(String root) throws javax.mail.MessagingException;
+
+ /**
+ * Set a quota item. The root contained in the Quota item identifies
+ * the quota target.
+ *
+ * @param quota The source quota item.
+ * @throws MessagingException if the quota cannot be set
+ */
+ public void setQuota(Quota quota) throws javax.mail.MessagingException;
+}
+
+
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/ReadOnlyFolderException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/ReadOnlyFolderException.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/ReadOnlyFolderException.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/ReadOnlyFolderException.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,58 @@
+/*
+ * 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.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ReadOnlyFolderException extends MessagingException {
+
+ private static final long serialVersionUID = 5711829372799039325L;
+
+ private transient Folder _folder;
+
+ public ReadOnlyFolderException(final Folder folder) {
+ this(folder, "Folder not found: " + folder.getName());
+ }
+
+ public ReadOnlyFolderException(final Folder folder, final String message) {
+ super(message);
+ _folder = folder;
+ }
+
+ /**
+ * Constructs a ReadOnlyFolderException 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 ReadOnlyFolderException(final Folder folder, final String message, final Exception e) {
+ super(message, e);
+ _folder = folder;
+ }
+
+ public Folder getFolder() {
+ return _folder;
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/SendFailedException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/SendFailedException.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/SendFailedException.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/SendFailedException.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,67 @@
+/*
+ * 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.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class SendFailedException extends MessagingException {
+
+ private static final long serialVersionUID = -6457531621682372913L;
+
+ protected transient Address invalid[];
+ protected transient Address validSent[];
+ protected transient Address validUnsent[];
+
+ public SendFailedException() {
+ super();
+ }
+
+ public SendFailedException(final String message) {
+ super(message);
+ }
+
+ public SendFailedException(final String message, final Exception cause) {
+ super(message, cause);
+ }
+
+ public SendFailedException(final String message,
+ final Exception cause,
+ final Address[] validSent,
+ final Address[] validUnsent,
+ final Address[] invalid) {
+ this(message, cause);
+ this.invalid = invalid;
+ this.validSent = validSent;
+ this.validUnsent = validUnsent;
+ }
+
+ public Address[] getValidSentAddresses() {
+ return validSent;
+ }
+
+ public Address[] getValidUnsentAddresses() {
+ return validUnsent;
+ }
+
+ public Address[] getInvalidAddresses() {
+ return invalid;
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Service.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Service.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Service.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Service.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,439 @@
+/*
+ * 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.mail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Vector;
+
+import javax.mail.event.ConnectionEvent;
+import javax.mail.event.ConnectionListener;
+import javax.mail.event.MailEvent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class Service {
+ /**
+ * The session from which this service was created.
+ */
+ protected Session session;
+ /**
+ * The URLName of this service
+ */
+ protected URLName url;
+ /**
+ * Debug flag for this service, set from the Session's debug flag.
+ */
+ protected boolean debug;
+
+ private boolean connected;
+ private final Vector connectionListeners = new Vector(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;
+ // when returning the URL, we need to ensure that the password and file information is
+ // stripped out.
+ private URLName exposedUrl;
+
+ /**
+ * Construct a new Service.
+ * @param session the session from which this service was created
+ * @param url the URLName of this service
+ */
+ protected Service(final Session session, final URLName url) {
+ this.session = session;
+ this.url = url;
+ this.debug = session.getDebug();
+ }
+
+ /**
+ * A generic connect method that takes no parameters allowing subclasses
+ * to implement an appropriate authentication scheme.
+ * The default implementation calls <code>connect(null, null, null)</code>
+ * @throws AuthenticationFailedException if authentication fails
+ * @throws MessagingException for other failures
+ */
+ public void connect() throws MessagingException {
+ connect(null, null, null);
+ }
+
+ /**
+ * Connect to the specified host using a simple username/password authenticaion scheme
+ * and the default port.
+ * The default implementation calls <code>connect(host, -1, user, password)</code>
+ *
+ * @param host the host to connect to
+ * @param user the user name
+ * @param password the user's password
+ * @throws AuthenticationFailedException if authentication fails
+ * @throws MessagingException for other failures
+ */
+ public void connect(final String host, final String user, final String password) throws MessagingException {
+ connect(host, -1, user, password);
+ }
+
+ /**
+ * Connect to the specified host using a simple username/password authenticaion scheme
+ * and the default host and port.
+ * The default implementation calls <code>connect(host, -1, user, password)</code>
+ *
+ * @param user the user name
+ * @param password the user's password
+ * @throws AuthenticationFailedException if authentication fails
+ * @throws MessagingException for other failures
+ */
+ public void connect(final String user, final String password) throws MessagingException {
+ connect(null, -1, user, password);
+ }
+
+ /**
+ * Connect to the specified host at the specified port using a simple username/password authenticaion scheme.
+ *
+ * If this Service is already connected, an IllegalStateException is thrown.
+ *
+ * @param host the host to connect to
+ * @param port the port to connect to; pass -1 to use the default for the protocol
+ * @param user the user name
+ * @param password the user's password
+ * @throws AuthenticationFailedException if authentication fails
+ * @throws MessagingException for other failures
+ * @throws IllegalStateException if this service is already connected
+ */
+ public void connect(String host, int port, String user, String password) throws MessagingException {
+
+ if (isConnected()) {
+ throw new IllegalStateException("Already connected");
+ }
+
+ // before we try to connect, we need to derive values for some parameters that may not have
+ // been explicitly specified. For example, the normal connect() method leaves us to derive all
+ // of these from other sources. Some of the values are derived from our URLName value, others
+ // from session parameters. We need to go through all of these to develop a set of values we
+ // can connect with.
+
+ // this is the protocol we're connecting with. We use this largely to derive configured values from
+ // session properties.
+ String protocol = null;
+
+ // if we're working with the URL form, then we can retrieve the protocol from the URL.
+ if (url != null) {
+ protocol = url.getProtocol();
+ }
+
+ // if the port is -1, see if we have an override from url.
+ if (port == -1) {
+ if (protocol != null) {
+ port = url.getPort();
+ }
+ }
+
+ // now try to derive values for any of the arguments we've been given as defaults
+ if (host == null) {
+ // first choice is from the url, if we have
+ if (url != null) {
+ host = url.getHost();
+ // it is possible that this could return null (rare). If it does, try to get a
+ // value from a protocol specific session variable.
+ if (host == null) {
+ if (protocol != null) {
+ host = session.getProperty("mail." + protocol + ".host");
+ }
+ }
+ }
+ // this may still be null...get the global mail property
+ if (host == null) {
+ host = session.getProperty("mail.host");
+ }
+ }
+
+ // ok, go after userid information next.
+ if (user == null) {
+ // first choice is from the url, if we have
+ if (url != null) {
+ user = url.getUsername();
+ // make sure we get the password from the url, if we can.
+ if (password == null) {
+ password = url.getPassword();
+ }
+ }
+
+ // user still null? We have several levels of properties to try yet
+ if (user == null) {
+ if (protocol != null) {
+ user = session.getProperty("mail." + protocol + ".user");
+ }
+
+ // this may still be null...get the global mail property
+ if (user == null) {
+ user = session.getProperty("mail.user");
+ // still null, try using the user.name system property
+ if (user == null) {
+ // finally, we try getting the system defined user name
+ try {
+ user = System.getProperty("user.name");
+ } catch (final SecurityException e) {
+ // we ignore this, and just us a null username.
+ }
+ }
+ }
+ }
+ }
+ // if we have an explicitly given user name, we need to see if this matches the url one and
+ // grab the password from there.
+ else {
+ if (url != null && user.equals(url.getUsername())) {
+ password = url.getPassword();
+ }
+ }
+
+ // we need to update the URLName associated with this connection once we have all of the information,
+ // which means we also need to propogate the file portion of the URLName if we have this form when
+ // we start.
+ String file = null;
+ if (url != null) {
+ file = url.getFile();
+ }
+
+ // see if we have cached security information to use. If this is not cached, we'll save it
+ // after we successfully connect.
+ boolean cachePassword = false;
+
+
+ // still have a null password to this point, and using a url form?
+ if (password == null && url != null) {
+ // construct a new URL, filling in any pieces that may have been explicitly specified.
+ setURLName(new URLName(protocol, host, port, file, user, password));
+ // now see if we have a saved password from a previous request.
+ final PasswordAuthentication cachedPassword = session.getPasswordAuthentication(getURLName());
+
+ // if we found a saved one, see if we need to get any the pieces from here.
+ if (cachedPassword != null) {
+ // not even a resolved userid? Then use both bits.
+ if (user == null) {
+ user = cachedPassword.getUserName();
+ password = cachedPassword.getPassword();
+ }
+ // our user name must match the cached name to be valid.
+ else if (user.equals(cachedPassword.getUserName())) {
+ password = cachedPassword.getPassword();
+ }
+ }
+ else
+ {
+ // nothing found in the cache, so we need to save this if we can connect successfully.
+ cachePassword = true;
+ }
+ }
+
+ // we've done our best up to this point to obtain all of the information needed to make the
+ // connection. Now we pass this off to the protocol handler to see if it works. If we get a
+ // connection failure, we may need to prompt for a password before continuing.
+ try {
+ connected = protocolConnect(host, port, user, password);
+ }
+ catch (final AuthenticationFailedException e) {
+ }
+
+ if (!connected) {
+ InetAddress ipAddress = null;
+
+ try {
+ ipAddress = InetAddress.getByName(host);
+ } catch (final UnknownHostException e) {
+ }
+
+ // now ask the session to try prompting for a password.
+ final PasswordAuthentication promptPassword = session.requestPasswordAuthentication(ipAddress, port, protocol, null, user);
+
+ // if we were able to obtain new information from the session, then try again using the
+ // provided information .
+ if (promptPassword != null) {
+ user = promptPassword.getUserName();
+ password = promptPassword.getPassword();
+ }
+
+ connected = protocolConnect(host, port, user, password);
+ }
+
+
+ // if we're still not connected, then this is an exception.
+ if (!connected) {
+ throw new AuthenticationFailedException();
+ }
+
+ // the URL name needs to reflect the most recent information.
+ setURLName(new URLName(protocol, host, port, file, user, password));
+
+ // we need to update the global password cache with this information.
+ if (cachePassword) {
+ session.setPasswordAuthentication(getURLName(), new PasswordAuthentication(user, password));
+ }
+
+ // we're now connected....broadcast this to any interested parties.
+ setConnected(connected);
+ notifyConnectionListeners(ConnectionEvent.OPENED);
+ }
+
+ /**
+ * Attempt the protocol-specific connection; subclasses should override this to establish
+ * a connection in the appropriate manner.
+ *
+ * This method should return true if the connection was established.
+ * It may return false to cause the {@link #connect(String, int, String, String)} method to
+ * reattempt the connection after trying to obtain user and password information from the user.
+ * Alternatively it may throw a AuthenticatedFailedException to abandon the conection attempt.
+ *
+ * @param host The target host name of the service.
+ * @param port The connection port for the service.
+ * @param user The user name used for the connection.
+ * @param password The password used for the connection.
+ *
+ * @return true if a connection was established, false if there was authentication
+ * error with the connection.
+ * @throws AuthenticationFailedException
+ * if authentication fails
+ * @throws MessagingException
+ * for other failures
+ */
+ protected boolean protocolConnect(final String host, final int port, final String user, final String password) throws MessagingException {
+ return false;
+ }
+
+ /**
+ * Check if this service is currently connected.
+ * The default implementation simply returns the value of a private boolean field;
+ * subclasses may wish to override this method to verify the physical connection.
+ *
+ * @return true if this service is connected
+ */
+ public boolean isConnected() {
+ return connected;
+ }
+
+ /**
+ * Notification to subclasses that the connection state has changed.
+ * This method is called by the connect() and close() methods to indicate state change;
+ * subclasses should also call this method if the connection is automatically closed
+ * for some reason.
+ *
+ * @param connected the connection state
+ */
+ protected void setConnected(final boolean connected) {
+ this.connected = connected;
+ }
+
+ /**
+ * Close this service and terminate its physical connection.
+ * The default implementation simply calls setConnected(false) and then
+ * sends a CLOSED event to all registered ConnectionListeners.
+ * Subclasses overriding this method should still ensure it is closed; they should
+ * also ensure that it is called if the connection is closed automatically, for
+ * for example in a finalizer.
+ *
+ *@throws MessagingException if there were errors closing; the connection is still closed
+ */
+ public void close() throws MessagingException {
+ setConnected(false);
+ notifyConnectionListeners(ConnectionEvent.CLOSED);
+ }
+
+ /**
+ * Return a copy of the URLName representing this service with the password and file information removed.
+ *
+ * @return the URLName for this service
+ */
+ public URLName getURLName() {
+ // if we haven't composed the URL version we hand out, create it now. But only if we really
+ // have a URL.
+ if (exposedUrl == null) {
+ if (url != null) {
+ exposedUrl = new URLName(url.getProtocol(), url.getHost(), url.getPort(), null, url.getUsername(), null);
+ }
+ }
+ return exposedUrl;
+ }
+
+ /**
+ * Set the url field.
+ * @param url the new value
+ */
+ protected void setURLName(final URLName url) {
+ this.url = url;
+ }
+
+ 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);
+ }
+
+ @Override
+ public String toString() {
+ // NOTE: We call getURLName() rather than use the URL directly
+ // because the get method strips out the password information.
+ final URLName url = getURLName();
+
+ return url == null ? super.toString() : url.toString();
+ }
+
+ protected void queueEvent(final MailEvent event, final Vector 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());
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ // stop our event queue if we had to create one
+ if (queue != null) {
+ queue.stop();
+ }
+ connectionListeners.clear();
+ super.finalize();
+ }
+
+
+ /**
+ * Package scope utility method to allow Message instances
+ * access to the Service's session.
+ *
+ * @return The Session the service is associated with.
+ */
+ Session getSession() {
+ return session;
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Session.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Session.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Session.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Session.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,860 @@
+/*
+ * 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.mail;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.WeakHashMap;
+
+import org.apache.geronimo.mail.MailProviderRegistry;
+import org.apache.geronimo.osgi.locator.ProviderLocator;
+
+/**
+ * OK, so we have a final class in the API with a heck of a lot of implementation required...
+ * let's try and figure out what it is meant to do.
+ * <p/>
+ * It is supposed to collect together properties and defaults so that they can be
+ * shared by multiple applications on a desktop; with process isolation and no
+ * real concept of shared memory, this seems challenging. These properties and
+ * defaults rely on system properties, making management in a app server harder,
+ * and on resources loaded from "mail.jar" which may lead to skew between
+ * differnet independent implementations of this API.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class Session {
+ private static final Class[] PARAM_TYPES = {Session.class, URLName.class};
+ private static final WeakHashMap addressMapsByClassLoader = new WeakHashMap();
+ private static Session DEFAULT_SESSION;
+
+ private final Map passwordAuthentications = new HashMap();
+
+ private final Properties properties;
+ private final Authenticator authenticator;
+ private boolean debug;
+ private PrintStream debugOut = System.out;
+
+ private static final WeakHashMap providersByClassLoader = new WeakHashMap();
+
+ /**
+ * No public constrcutor allowed.
+ */
+ private Session(final Properties properties, final Authenticator authenticator) {
+ this.properties = properties;
+ this.authenticator = authenticator;
+ debug = Boolean.valueOf(properties.getProperty("mail.debug")).booleanValue();
+ }
+
+ /**
+ * Create a new session initialized with the supplied properties which uses the supplied authenticator.
+ * Clients should ensure the properties listed in Appendix A of the JavaMail specification are
+ * set as the defaults are unlikey to work in most scenarios; particular attention should be given
+ * to:
+ * <ul>
+ * <li>mail.store.protocol</li>
+ * <li>mail.transport.protocol</li>
+ * <li>mail.host</li>
+ * <li>mail.user</li>
+ * <li>mail.from</li>
+ * </ul>
+ *
+ * @param properties the session properties
+ * @param authenticator an authenticator for callbacks to the user
+ * @return a new session
+ */
+ public static Session getInstance(Properties properties, final Authenticator authenticator) {
+ // if we have a properties bundle, we need a copy of the provided one
+ if (properties != null) {
+ properties = (Properties)properties.clone();
+ }
+
+ return new Session(properties, authenticator);
+ }
+
+ /**
+ * Create a new session initialized with the supplied properties with no authenticator.
+ *
+ * @param properties the session properties
+ * @return a new session
+ * @see #getInstance(java.util.Properties, Authenticator)
+ */
+ public static Session getInstance(final Properties properties) {
+ return getInstance(properties, null);
+ }
+
+ /**
+ * Get the "default" instance assuming no authenticator is required.
+ *
+ * @param properties the session properties
+ * @return if "default" session
+ * @throws SecurityException if the does not have permission to access the default session
+ */
+ public synchronized static Session getDefaultInstance(final Properties properties) {
+ return getDefaultInstance(properties, null);
+ }
+
+ /**
+ * Get the "default" session.
+ * If there is not current "default", a new Session is created and installed as the default.
+ *
+ * @param properties
+ * @param authenticator
+ * @return if "default" session
+ * @throws SecurityException if the does not have permission to access the default session
+ */
+ public synchronized static Session getDefaultInstance(final Properties properties, final Authenticator authenticator) {
+ if (DEFAULT_SESSION == null) {
+ DEFAULT_SESSION = getInstance(properties, authenticator);
+ } else {
+ if (authenticator != DEFAULT_SESSION.authenticator) {
+ if (authenticator == null || DEFAULT_SESSION.authenticator == null || authenticator.getClass().getClassLoader() != DEFAULT_SESSION.authenticator.getClass().getClassLoader()) {
+ throw new SecurityException();
+ }
+ }
+ // todo we should check with the SecurityManager here as well
+ }
+ return DEFAULT_SESSION;
+ }
+
+ /**
+ * Enable debugging for this session.
+ * Debugging can also be enabled by setting the "mail.debug" property to true when
+ * the session is being created.
+ *
+ * @param debug the debug setting
+ */
+ public void setDebug(final boolean debug) {
+ this.debug = debug;
+ }
+
+ /**
+ * Get the debug setting for this session.
+ *
+ * @return the debug setting
+ */
+ public boolean getDebug() {
+ return debug;
+ }
+
+ /**
+ * Set the output stream where debug information should be sent.
+ * If set to null, System.out will be used.
+ *
+ * @param out the stream to write debug information to
+ */
+ public void setDebugOut(final PrintStream out) {
+ debugOut = out == null ? System.out : out;
+ }
+
+ /**
+ * Return the debug output stream.
+ *
+ * @return the debug output stream
+ */
+ public PrintStream getDebugOut() {
+ return debugOut;
+ }
+
+ /**
+ * Return the list of providers available to this application.
+ * This method searches for providers that are defined in the javamail.providers
+ * and javamail.default.providers resources available through the current context
+ * classloader, or if that is not available, the classloader that loaded this class.
+ * <p/>
+ * As searching for providers is potentially expensive, this implementation maintains
+ * a WeakHashMap of providers indexed by ClassLoader.
+ *
+ * @return an array of providers
+ */
+ public Provider[] getProviders() {
+ final ProviderInfo info = getProviderInfo();
+ return (Provider[]) info.all.toArray(new Provider[info.all.size()]);
+ }
+
+ /**
+ * Return the provider for a specific protocol.
+ * This implementation initially looks in the Session properties for an property with the name
+ * "mail.<protocol>.class"; if found it attempts to create an instance of the class named in that
+ * property throwing a NoSuchProviderException if the class cannot be loaded.
+ * If this property is not found, it searches the providers returned by {@link #getProviders()}
+ * for a entry for the specified protocol.
+ *
+ * @param protocol the protocol to get a provider for
+ * @return a provider for that protocol
+ * @throws NoSuchProviderException
+ */
+ public Provider getProvider(final String protocol) throws NoSuchProviderException {
+ final ProviderInfo info = getProviderInfo();
+ Provider provider = null;
+ final String providerName = properties.getProperty("mail." + protocol + ".class");
+ if (providerName != null) {
+ provider = (Provider) info.byClassName.get(providerName);
+ if (debug) {
+ writeDebug("DEBUG: new provider loaded: " + provider.toString());
+ }
+ }
+
+ // if not able to locate this by class name, just grab a registered protocol.
+ if (provider == null) {
+ provider = (Provider) info.byProtocol.get(protocol);
+ }
+
+ if (provider == null) {
+ throw new NoSuchProviderException("Unable to locate provider for protocol: " + protocol);
+ }
+ if (debug) {
+ writeDebug("DEBUG: getProvider() returning provider " + provider.toString());
+ }
+ return provider;
+ }
+
+ /**
+ * Make the supplied Provider the default for its protocol.
+ *
+ * @param provider the new default Provider
+ * @throws NoSuchProviderException
+ */
+ public void setProvider(final Provider provider) throws NoSuchProviderException {
+ final ProviderInfo info = getProviderInfo();
+ info.byProtocol.put(provider.getProtocol(), provider);
+ }
+
+ /**
+ * Return a Store for the default protocol defined by the mail.store.protocol property.
+ *
+ * @return the store for the default protocol
+ * @throws NoSuchProviderException
+ */
+ public Store getStore() throws NoSuchProviderException {
+ final String protocol = properties.getProperty("mail.store.protocol");
+ if (protocol == null) {
+ throw new NoSuchProviderException("mail.store.protocol property is not set");
+ }
+ return getStore(protocol);
+ }
+
+ /**
+ * Return a Store for the specified protocol.
+ *
+ * @param protocol the protocol to get a Store for
+ * @return a Store
+ * @throws NoSuchProviderException if no provider is defined for the specified protocol
+ */
+ public Store getStore(final String protocol) throws NoSuchProviderException {
+ final Provider provider = getProvider(protocol);
+ return getStore(provider);
+ }
+
+ /**
+ * Return a Store for the protocol specified in the given URL
+ *
+ * @param url the URL of the Store
+ * @return a Store
+ * @throws NoSuchProviderException if no provider is defined for the specified protocol
+ */
+ public Store getStore(final URLName url) throws NoSuchProviderException {
+ return (Store) getService(getProvider(url.getProtocol()), url);
+ }
+
+ /**
+ * Return the Store specified by the given provider.
+ *
+ * @param provider the provider to create from
+ * @return a Store
+ * @throws NoSuchProviderException if there was a problem creating the Store
+ */
+ public Store getStore(final Provider provider) throws NoSuchProviderException {
+ if (Provider.Type.STORE != provider.getType()) {
+ throw new NoSuchProviderException("Not a Store Provider: " + provider);
+ }
+ return (Store) getService(provider, null);
+ }
+
+ /**
+ * Return a closed folder for the supplied URLName, or null if it cannot be obtained.
+ * <p/>
+ * The scheme portion of the URL is used to locate the Provider and create the Store;
+ * the returned Store is then used to obtain the folder.
+ *
+ * @param name the location of the folder
+ * @return the requested folder, or null if it is unavailable
+ * @throws NoSuchProviderException if there is no provider
+ * @throws MessagingException if there was a problem accessing the Store
+ */
+ public Folder getFolder(final URLName name) throws MessagingException {
+ final Store store = getStore(name);
+ return store.getFolder(name);
+ }
+
+ /**
+ * Return a Transport for the default protocol specified by the
+ * <code>mail.transport.protocol</code> property.
+ *
+ * @return a Transport
+ * @throws NoSuchProviderException
+ */
+ public Transport getTransport() throws NoSuchProviderException {
+ final String protocol = properties.getProperty("mail.transport.protocol");
+ if (protocol == null) {
+ throw new NoSuchProviderException("mail.transport.protocol property is not set");
+ }
+ return getTransport(protocol);
+ }
+
+ /**
+ * Return a Transport for the specified protocol.
+ *
+ * @param protocol the protocol to use
+ * @return a Transport
+ * @throws NoSuchProviderException
+ */
+ public Transport getTransport(final String protocol) throws NoSuchProviderException {
+ final Provider provider = getProvider(protocol);
+ return getTransport(provider);
+ }
+
+ /**
+ * Return a transport for the protocol specified in the URL.
+ *
+ * @param name the URL whose scheme specifies the protocol
+ * @return a Transport
+ * @throws NoSuchProviderException
+ */
+ public Transport getTransport(final URLName name) throws NoSuchProviderException {
+ return (Transport) getService(getProvider(name.getProtocol()), name);
+ }
+
+ /**
+ * Return a transport for the protocol associated with the type of this address.
+ *
+ * @param address the address we are trying to deliver to
+ * @return a Transport
+ * @throws NoSuchProviderException
+ */
+ public Transport getTransport(final Address address) throws NoSuchProviderException {
+ final String type = address.getType();
+ // load the address map from the resource files.
+ final Map addressMap = getAddressMap();
+ final String protocolName = (String)addressMap.get(type);
+ if (protocolName == null) {
+ throw new NoSuchProviderException("No provider for address type " + type);
+ }
+ return getTransport(protocolName);
+ }
+
+ /**
+ * Return the Transport specified by a Provider
+ *
+ * @param provider the defining Provider
+ * @return a Transport
+ * @throws NoSuchProviderException
+ */
+ public Transport getTransport(final Provider provider) throws NoSuchProviderException {
+ return (Transport) getService(provider, null);
+ }
+
+ /**
+ * Set the password authentication associated with a URL.
+ *
+ * @param name the url
+ * @param authenticator the authenticator
+ */
+ public void setPasswordAuthentication(final URLName name, final PasswordAuthentication authenticator) {
+ if (authenticator == null) {
+ passwordAuthentications.remove(name);
+ } else {
+ passwordAuthentications.put(name, authenticator);
+ }
+ }
+
+ /**
+ * Get the password authentication associated with a URL
+ *
+ * @param name the URL
+ * @return any authenticator for that url, or null if none
+ */
+ public PasswordAuthentication getPasswordAuthentication(final URLName name) {
+ return (PasswordAuthentication) passwordAuthentications.get(name);
+ }
+
+ /**
+ * Call back to the application supplied authenticator to get the needed username add password.
+ *
+ * @param host the host we are trying to connect to, may be null
+ * @param port the port on that host
+ * @param protocol the protocol trying to be used
+ * @param prompt a String to show as part of the prompt, may be null
+ * @param defaultUserName the default username, may be null
+ * @return the authentication information collected by the authenticator; may be null
+ */
+ public PasswordAuthentication requestPasswordAuthentication(final InetAddress host, final int port, final String protocol, final String prompt, final String defaultUserName) {
+ if (authenticator == null) {
+ return null;
+ }
+ return authenticator.authenticate(host, port, protocol, prompt, defaultUserName);
+ }
+
+ /**
+ * Return the properties object for this Session; this is a live collection.
+ *
+ * @return the properties for the Session
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Return the specified property.
+ *
+ * @param property the property to get
+ * @return its value, or null if not present
+ */
+ public String getProperty(final String property) {
+ return getProperties().getProperty(property);
+ }
+
+
+ /**
+ * Add a provider to the Session managed provider list.
+ *
+ * @param provider The new provider to add.
+ */
+ public synchronized void addProvider(final Provider provider) {
+ final ProviderInfo info = getProviderInfo();
+ info.addProvider(provider);
+ }
+
+
+
+ /**
+ * Add a mapping between an address type and a protocol used
+ * to process that address type.
+ *
+ * @param addressType
+ * The address type identifier.
+ * @param protocol The protocol name mapping.
+ */
+ public void setProtocolForAddress(final String addressType, final String protocol) {
+ final Map addressMap = getAddressMap();
+
+ // no protocol specified is a removal
+ if (protocol == null) {
+ addressMap.remove(addressType);
+ }
+ else {
+ addressMap.put(addressType, protocol);
+ }
+ }
+
+
+ private Service getService(final Provider provider, URLName name) throws NoSuchProviderException {
+ try {
+ if (name == null) {
+ name = new URLName(provider.getProtocol(), null, -1, null, null, null);
+ }
+ final ClassLoader cl = getClassLoader();
+ Class clazz = null;
+ try {
+ clazz = ProviderLocator.loadClass(provider.getClassName(), this.getClass(), cl);
+ } catch (final ClassNotFoundException e) {
+ throw (NoSuchProviderException) new NoSuchProviderException("Unable to load class for provider: " + provider).initCause(e);
+ }
+ final Constructor ctr = clazz.getConstructor(PARAM_TYPES);
+ return(Service) ctr.newInstance(new Object[]{this, name});
+ } catch (final NoSuchMethodException e) {
+ throw (NoSuchProviderException) new NoSuchProviderException("Provider class does not have a constructor(Session, URLName): " + provider).initCause(e);
+ } catch (final InstantiationException e) {
+ throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
+ } catch (final IllegalAccessException e) {
+ throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
+ } catch (final InvocationTargetException e) {
+ throw (NoSuchProviderException) new NoSuchProviderException("Exception from constructor of provider class: " + provider).initCause(e.getCause());
+ }
+ }
+
+ private ProviderInfo getProviderInfo() {
+ final ClassLoader cl = getClassLoader();
+ synchronized (providersByClassLoader) {
+ ProviderInfo info = (ProviderInfo) providersByClassLoader.get(cl);
+ if (info == null) {
+ info = loadProviders(cl);
+ }
+ return info;
+ }
+ }
+
+ private Map getAddressMap() {
+ final ClassLoader cl = getClassLoader();
+ Map addressMap = (Map)addressMapsByClassLoader.get(cl);
+ if (addressMap == null) {
+ addressMap = loadAddressMap(cl);
+ }
+ return addressMap;
+ }
+
+
+ /**
+ * Resolve a class loader used to resolve context resources. The
+ * class loader used is either a current thread context class
+ * loader (if set), the class loader used to load an authenticator
+ * we've been initialized with, or the class loader used to load
+ * this class instance (which may be a subclass of Session).
+ *
+ * @return The class loader used to load resources.
+ */
+ private ClassLoader getClassLoader() {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if (cl == null) {
+ if (authenticator != null) {
+ cl = authenticator.getClass().getClassLoader();
+ }
+ else {
+ cl = this.getClass().getClassLoader();
+ }
+ }
+ return cl;
+ }
+
+ private ProviderInfo loadProviders(final ClassLoader cl) {
+ // we create a merged map from reading all of the potential address map entries. The locations
+ // searched are:
+ // 1. java.home/lib/javamail.address.map
+ // 2. META-INF/javamail.address.map
+ // 3. META-INF/javamail.default.address.map
+ //
+ final ProviderInfo info = new ProviderInfo();
+
+ // NOTE: Unlike the addressMap, we process these in the defined order. The loading routine
+ // will not overwrite entries if they already exist in the map.
+
+ try {
+ final File file = new File(System.getProperty("java.home"), "lib/javamail.providers");
+ final InputStream is = new FileInputStream(file);
+ try {
+ loadProviders(info, is);
+ if (debug) {
+ writeDebug("Loaded lib/javamail.providers from " + file.toString());
+ }
+ } finally{
+ is.close();
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ try {
+ final Enumeration e = cl.getResources("META-INF/javamail.providers");
+ while (e.hasMoreElements()) {
+ final URL url = (URL) e.nextElement();
+ if (debug) {
+ writeDebug("Loading META-INF/javamail.providers from " + url.toString());
+ }
+ final InputStream is = url.openStream();
+ try {
+ loadProviders(info, is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ // we could be running in an OSGi environment, so there might be some globally defined
+ // providers
+ try {
+ final Collection<URL> l = MailProviderRegistry.getProviders();
+ for (final URL url : l) {
+ if (debug) {
+ writeDebug("Loading META-INF/javamail.providers from " + url.toString());
+ }
+ final InputStream is = url.openStream();
+ try {
+ loadProviders(info, is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ try {
+ final Enumeration e = cl.getResources("META-INF/javamail.default.providers");
+ while (e.hasMoreElements()) {
+ final URL url = (URL) e.nextElement();
+ if (debug) {
+ writeDebug("Loading javamail.default.providers from " + url.toString());
+ }
+
+ final InputStream is = url.openStream();
+ try {
+ loadProviders(info, is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ // we could be running in an OSGi environment, so there might be some globally defined
+ // providers
+ try {
+ final Collection<URL> l = MailProviderRegistry.getDefaultProviders();
+ for (final URL url : l) {
+ if (debug) {
+ writeDebug("Loading META-INF/javamail.providers from " + url.toString());
+ }
+ final InputStream is = url.openStream();
+ try {
+ loadProviders(info, is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ // make sure this is added to the global map.
+ providersByClassLoader.put(cl, info);
+
+ return info;
+ }
+
+ private void loadProviders(final ProviderInfo info, final InputStream is) throws IOException {
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // Lines beginning with "#" are just comments.
+ if (line.startsWith("#")) {
+ continue;
+ }
+
+ final StringTokenizer tok = new StringTokenizer(line, ";");
+ String protocol = null;
+ Provider.Type type = null;
+ String className = null;
+ String vendor = null;
+ String version = null;
+ while (tok.hasMoreTokens()) {
+ final String property = tok.nextToken();
+ final int index = property.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ final String key = property.substring(0, index).trim().toLowerCase();
+ final String value = property.substring(index+1).trim();
+ if (protocol == null && "protocol".equals(key)) {
+ protocol = value;
+ } else if (type == null && "type".equals(key)) {
+ if ("store".equals(value)) {
+ type = Provider.Type.STORE;
+ } else if ("transport".equals(value)) {
+ type = Provider.Type.TRANSPORT;
+ }
+ } else if (className == null && "class".equals(key)) {
+ className = value;
+ } else if ("vendor".equals(key)) {
+ vendor = value;
+ } else if ("version".equals(key)) {
+ version = value;
+ }
+ }
+ if (protocol == null || type == null || className == null) {
+ //todo should we log a warning?
+ continue;
+ }
+
+ if (debug) {
+ writeDebug("DEBUG: loading new provider protocol=" + protocol + ", className=" + className + ", vendor=" + vendor + ", version=" + version);
+ }
+ final Provider provider = new Provider(type, protocol, className, vendor, version);
+ // add to the info list.
+ info.addProvider(provider);
+ }
+ }
+
+ /**
+ * Load up an address map associated with a using class loader
+ * instance.
+ *
+ * @param cl The class loader used to resolve the address map.
+ *
+ * @return A map containing the entries associated with this classloader
+ * instance.
+ */
+ private static Map loadAddressMap(final ClassLoader cl) {
+ // we create a merged map from reading all of the potential address map entries. The locations
+ // searched are:
+ // 1. java.home/lib/javamail.address.map
+ // 2. META-INF/javamail.address.map
+ // 3. META-INF/javamail.default.address.map
+ //
+ // if all of the above searches fail, we just set up some "default" defaults.
+
+ // the format of the address.map file is defined as a property file. We can cheat and
+ // just use Properties.load() to read in the files.
+ final Properties addressMap = new Properties();
+
+ // add this to the tracking map.
+ addressMapsByClassLoader.put(cl, addressMap);
+
+ // NOTE: We are reading these resources in reverse order of what's cited above. This allows
+ // user defined entries to overwrite default entries if there are similarly named items.
+
+ try {
+ final Enumeration e = cl.getResources("META-INF/javamail.default.address.map");
+ while (e.hasMoreElements()) {
+ final URL url = (URL) e.nextElement();
+ final InputStream is = url.openStream();
+ try {
+ // load as a property file
+ addressMap.load(is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+
+ try {
+ final Enumeration e = cl.getResources("META-INF/javamail.address.map");
+ while (e.hasMoreElements()) {
+ final URL url = (URL) e.nextElement();
+ final InputStream is = url.openStream();
+ try {
+ // load as a property file
+ addressMap.load(is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+
+ try {
+ final File file = new File(System.getProperty("java.home"), "lib/javamail.address.map");
+ final InputStream is = new FileInputStream(file);
+ try {
+ // load as a property file
+ addressMap.load(is);
+ } finally{
+ is.close();
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+ try {
+ final Enumeration e = cl.getResources("META-INF/javamail.address.map");
+ while (e.hasMoreElements()) {
+ final URL url = (URL) e.nextElement();
+ final InputStream is = url.openStream();
+ try {
+ // load as a property file
+ addressMap.load(is);
+ } finally{
+ is.close();
+ }
+ }
+ } catch (final SecurityException e) {
+ // ignore
+ } catch (final IOException e) {
+ // ignore
+ }
+
+
+ // if unable to load anything, at least create the MimeMessage-smtp protocol mapping.
+ if (addressMap.isEmpty()) {
+ addressMap.put("rfc822", "smtp");
+ }
+
+ return addressMap;
+ }
+
+ /**
+ * Private convenience routine for debug output.
+ *
+ * @param msg The message to write out to the debug stream.
+ */
+ private void writeDebug(final String msg) {
+ debugOut.println(msg);
+ }
+
+
+ private static class ProviderInfo {
+ private final Map byClassName = new HashMap();
+ private final Map byProtocol = new HashMap();
+ private final List all = new ArrayList();
+
+ public void addProvider(final Provider provider) {
+ final String className = provider.getClassName();
+
+ if (!byClassName.containsKey(className)) {
+ byClassName.put(className, provider);
+ }
+
+ final String protocol = provider.getProtocol();
+ if (!byProtocol.containsKey(protocol)) {
+ byProtocol.put(protocol, provider);
+ }
+ all.add(provider);
+ }
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Store.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Store.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Store.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/Store.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,145 @@
+/*
+ * 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.mail;
+
+import java.util.Vector;
+
+import javax.mail.event.FolderEvent;
+import javax.mail.event.FolderListener;
+import javax.mail.event.StoreEvent;
+import javax.mail.event.StoreListener;
+
+/**
+ * Abstract class that represents a message store.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class Store extends Service {
+ private static final Folder[] FOLDER_ARRAY = new Folder[0];
+ private final Vector folderListeners = new Vector(2);
+ private final Vector storeListeners = new Vector(2);
+
+ /**
+ * Constructor specifying session and url of this store.
+ * Subclasses MUST provide a constructor with this signature.
+ *
+ * @param session the session associated with this store
+ * @param name the URL of the store
+ */
+ protected Store(final Session session, final URLName name) {
+ super(session, name);
+ }
+
+ /**
+ * Return a Folder object that represents the root of the namespace for the current user.
+ *
+ * Note that in some store configurations (such as IMAP4) the root folder might
+ * not be the INBOX folder.
+ *
+ * @return the root Folder
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public abstract Folder getDefaultFolder() throws MessagingException;
+
+ /**
+ * Return the Folder corresponding to the given name.
+ * The folder might not physically exist; the {@link Folder#exists()} method can be used
+ * to determine if it is real.
+ * @param name the name of the Folder to return
+ * @return the corresponding folder
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public abstract Folder getFolder(String name) throws MessagingException;
+
+ /**
+ * Return the folder identified by the URLName; the URLName must refer to this Store.
+ * Implementations may use the {@link URLName#getFile()} method to determined the folder name.
+ *
+ * @param name the folder to return
+ * @return the corresponding folder
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public abstract Folder getFolder(URLName name) throws MessagingException;
+
+ /**
+ * Return the root folders of the personal namespace belonging to the current user.
+ *
+ * The default implementation simply returns an array containing the folder returned by {@link #getDefaultFolder()}.
+ * @return the root folders of the user's peronal namespaces
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public Folder[] getPersonalNamespaces() throws MessagingException {
+ return new Folder[]{getDefaultFolder()};
+ }
+
+ /**
+ * Return the root folders of the personal namespaces belonging to the supplied user.
+ *
+ * The default implementation simply returns an empty array.
+ *
+ * @param user the user whose namespaces should be returned
+ * @return the root folders of the given user's peronal namespaces
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public Folder[] getUserNamespaces(final String user) throws MessagingException {
+ return FOLDER_ARRAY;
+ }
+
+ /**
+ * Return the root folders of namespaces that are intended to be shared between users.
+ *
+ * The default implementation simply returns an empty array.
+ * @return the root folders of all shared namespaces
+ * @throws MessagingException if there was a problem accessing the store
+ */
+ public Folder[] getSharedNamespaces() throws MessagingException {
+ return FOLDER_ARRAY;
+ }
+
+
+ public void addStoreListener(final StoreListener listener) {
+ storeListeners.add(listener);
+ }
+
+ public void removeStoreListener(final StoreListener listener) {
+ storeListeners.remove(listener);
+ }
+
+ protected void notifyStoreListeners(final int type, final String message) {
+ queueEvent(new StoreEvent(this, type, message), storeListeners);
+ }
+
+
+ public void addFolderListener(final FolderListener listener) {
+ folderListeners.add(listener);
+ }
+
+ public void removeFolderListener(final FolderListener listener) {
+ folderListeners.remove(listener);
+ }
+
+ protected void notifyFolderListeners(final int type, final Folder folder) {
+ queueEvent(new FolderEvent(this, folder, type), folderListeners);
+ }
+
+ protected void notifyFolderRenamedListeners(final Folder oldFolder, final Folder newFolder) {
+ queueEvent(new FolderEvent(this, oldFolder, newFolder, FolderEvent.RENAMED), folderListeners);
+ }
+}
Added: geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/StoreClosedException.java
URL: http://svn.apache.org/viewvc/geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/StoreClosedException.java?rev=1866401&view=auto
==============================================================================
--- geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/StoreClosedException.java (added)
+++ geronimo/specs/trunk/geronimo-javamail_1.6_spec/src/main/java/javax/mail/StoreClosedException.java Wed Sep 4 16:45:48 2019
@@ -0,0 +1,59 @@
+/*
+ * 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.mail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class StoreClosedException extends MessagingException {
+
+ private static final long serialVersionUID = -3145392336120082655L;
+
+ private transient Store _store;
+
+ public StoreClosedException(final Store store) {
+ super();
+ _store = store;
+ }
+
+ public StoreClosedException(final Store store, final String message) {
+ super(message);
+ _store = store;
+ }
+
+ /**
+ * Constructs a StoreClosedException with the specified
+ * detail message and embedded exception. The exception is chained
+ * to this exception.
+ *
+ * @param store The dead Store object
+ * @param message The detailed error message
+ * @param e The embedded exception
+ * @since JavaMail 1.5
+ */
+ public StoreClosedException(final Store store, final String message, final Exception e) {
+ super(message, e);
+ _store = store;
+ }
+
+ public Store getStore() {
+ return _store;
+ }
+}