0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0N/A *
503N/A * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * The contents of this file are subject to the terms of either the GNU
0N/A * General Public License Version 2 only ("GPL") or the Common Development
0N/A * and Distribution License("CDDL") (collectively, the "License"). You
292N/A * may not use this file except in compliance with the License. You can
292N/A * obtain a copy of the License at
292N/A * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
292N/A * or packager/legal/LICENSE.txt. See the License for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing the software, include this License Header Notice in each
292N/A * file and include the License file at packager/legal/LICENSE.txt.
292N/A *
292N/A * GPL Classpath Exception:
292N/A * Oracle designates this particular file as subject to the "Classpath"
292N/A * exception as provided by Oracle in the GPL Version 2 section of the License
292N/A * file that accompanied this code.
292N/A *
292N/A * Modifications:
292N/A * If applicable, add the following below the License Header, with the fields
292N/A * enclosed by brackets [] replaced by your own identifying information:
292N/A * "Portions Copyright [year] [name of copyright owner]"
0N/A *
0N/A * Contributor(s):
0N/A * If you wish your version of this file to be governed by only the CDDL or
0N/A * only the GPL Version 2, indicate your decision by adding "[Contributor]
0N/A * elects to include this software in this distribution under the [CDDL or GPL
0N/A * Version 2] license." If you don't indicate a single choice of license, a
0N/A * recipient has the option to distribute your version of this file under
0N/A * either the CDDL, the GPL Version 2 or to extend the choice of license to
0N/A * its licensees as provided above. However, if you add GPL Version 2 code
0N/A * and therefore, elected the GPL Version 2 license, then the option applies
0N/A * only if the new code is made subject to such option by the copyright
0N/A * holder.
0N/A */
0N/A
0N/Apackage javax.mail;
0N/A
0N/Aimport java.io.Serializable;
0N/Aimport java.util.*;
0N/A
0N/A/**
0N/A * The Flags class represents the set of flags on a Message. Flags
0N/A * are composed of predefined system flags, and user defined flags. <p>
0N/A *
0N/A * A System flag is represented by the <code>Flags.Flag</code>
0N/A * inner class. A User defined flag is represented as a String.
0N/A * User flags are case-independent. <p>
0N/A *
0N/A * A set of standard system flags are predefined. Most folder
0N/A * implementations are expected to support these flags. Some
0N/A * implementations may also support arbitrary user-defined flags. The
0N/A * <code>getPermanentFlags</code> method on a Folder returns a Flags
0N/A * object that holds all the flags that are supported by that folder
0N/A * implementation. <p>
0N/A *
0N/A * A Flags object is serializable so that (for example) the
0N/A * use of Flags objects in search terms can be serialized
0N/A * along with the search terms. <p>
0N/A *
0N/A * <strong>Warning:</strong>
0N/A * Serialized objects of this class may not be compatible with future
0N/A * JavaMail API releases. The current serialization support is
0N/A * appropriate for short term storage. <p>
0N/A *
503N/A * The below code sample illustrates how to set, examine, and get the
611N/A * flags for a message.
0N/A * <pre>
0N/A *
0N/A * Message m = folder.getMessage(1);
0N/A * m.setFlag(Flags.Flag.DELETED, true); // set the DELETED flag
0N/A *
503N/A * // Check if DELETED flag is set on this message
0N/A * if (m.isSet(Flags.Flag.DELETED))
0N/A * System.out.println("DELETED message");
0N/A *
0N/A * // Examine ALL system flags for this message
0N/A * Flags flags = m.getFlags();
0N/A * Flags.Flag[] sf = flags.getSystemFlags();
610N/A * for (int i = 0; i &lt; sf.length; i++) {
0N/A * if (sf[i] == Flags.Flag.DELETED)
0N/A * System.out.println("DELETED message");
0N/A * else if (sf[i] == Flags.Flag.SEEN)
0N/A * System.out.println("SEEN message");
0N/A * ......
0N/A * ......
0N/A * }
0N/A * </pre>
0N/A * <p>
0N/A *
0N/A * @see Folder#getPermanentFlags
0N/A * @author John Mani
0N/A * @author Bill Shannon
0N/A */
0N/A
0N/Apublic class Flags implements Cloneable, Serializable {
0N/A
0N/A private int system_flags = 0;
787N/A private Hashtable<String, String> user_flags = null;
0N/A
0N/A private final static int ANSWERED_BIT = 0x01;
0N/A private final static int DELETED_BIT = 0x02;
0N/A private final static int DRAFT_BIT = 0x04;
0N/A private final static int FLAGGED_BIT = 0x08;
0N/A private final static int RECENT_BIT = 0x10;
0N/A private final static int SEEN_BIT = 0x20;
0N/A private final static int USER_BIT = 0x80000000;
0N/A
0N/A private static final long serialVersionUID = 6243590407214169028L;
0N/A
0N/A /**
0N/A * This inner class represents an individual system flag. A set
0N/A * of standard system flag objects are predefined here.
0N/A */
0N/A public static final class Flag {
0N/A /**
0N/A * This message has been answered. This flag is set by clients
0N/A * to indicate that this message has been answered to.
0N/A */
0N/A public static final Flag ANSWERED = new Flag(ANSWERED_BIT);
0N/A
0N/A /**
0N/A * This message is marked deleted. Clients set this flag to
0N/A * mark a message as deleted. The expunge operation on a folder
0N/A * removes all messages in that folder that are marked for deletion.
0N/A */
0N/A public static final Flag DELETED = new Flag(DELETED_BIT);
0N/A
0N/A /**
0N/A * This message is a draft. This flag is set by clients
0N/A * to indicate that the message is a draft message.
0N/A */
0N/A public static final Flag DRAFT = new Flag(DRAFT_BIT);
0N/A
0N/A /**
0N/A * This message is flagged. No semantic is defined for this flag.
0N/A * Clients alter this flag.
0N/A */
0N/A public static final Flag FLAGGED = new Flag(FLAGGED_BIT);
0N/A
0N/A /**
0N/A * This message is recent. Folder implementations set this flag
0N/A * to indicate that this message is new to this folder, that is,
0N/A * it has arrived since the last time this folder was opened. <p>
0N/A *
0N/A * Clients cannot alter this flag.
0N/A */
0N/A public static final Flag RECENT = new Flag(RECENT_BIT);
0N/A
0N/A /**
0N/A * This message is seen. This flag is implicitly set by the
0N/A * implementation when the this Message's content is returned
0N/A * to the client in some form. The <code>getInputStream</code>
0N/A * and <code>getContent</code> methods on Message cause this
0N/A * flag to be set. <p>
0N/A *
0N/A * Clients can alter this flag.
0N/A */
0N/A public static final Flag SEEN = new Flag(SEEN_BIT);
0N/A
0N/A /**
0N/A * A special flag that indicates that this folder supports
0N/A * user defined flags. <p>
0N/A *
0N/A * The implementation sets this flag. Clients cannot alter
0N/A * this flag but can use it to determine if a folder supports
0N/A * user defined flags by using
0N/A * <code>folder.getPermanentFlags().contains(Flags.Flag.USER)</code>.
0N/A */
0N/A public static final Flag USER = new Flag(USER_BIT);
0N/A
0N/A // flags are stored as bits for efficiency
0N/A private int bit;
0N/A private Flag(int bit) {
0N/A this.bit = bit;
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Construct an empty Flags object.
0N/A */
0N/A public Flags() { }
0N/A
0N/A /**
0N/A * Construct a Flags object initialized with the given flags.
0N/A *
0N/A * @param flags the flags for initialization
0N/A */
787N/A @SuppressWarnings("unchecked")
0N/A public Flags(Flags flags) {
0N/A this.system_flags = flags.system_flags;
0N/A if (flags.user_flags != null)
0N/A this.user_flags = (Hashtable)flags.user_flags.clone();
0N/A }
0N/A
0N/A /**
0N/A * Construct a Flags object initialized with the given system flag.
0N/A *
0N/A * @param flag the flag for initialization
0N/A */
0N/A public Flags(Flag flag) {
0N/A this.system_flags |= flag.bit;
0N/A }
0N/A
0N/A /**
0N/A * Construct a Flags object initialized with the given user flag.
0N/A *
0N/A * @param flag the flag for initialization
0N/A */
0N/A public Flags(String flag) {
787N/A user_flags = new Hashtable<String, String>(1);
0N/A user_flags.put(flag.toLowerCase(Locale.ENGLISH), flag);
0N/A }
0N/A
0N/A /**
0N/A * Add the specified system flag to this Flags object.
0N/A *
0N/A * @param flag the flag to add
0N/A */
0N/A public void add(Flag flag) {
0N/A system_flags |= flag.bit;
0N/A }
0N/A
0N/A /**
0N/A * Add the specified user flag to this Flags object.
0N/A *
0N/A * @param flag the flag to add
0N/A */
0N/A public void add(String flag) {
0N/A if (user_flags == null)
787N/A user_flags = new Hashtable<String, String>(1);
0N/A user_flags.put(flag.toLowerCase(Locale.ENGLISH), flag);
0N/A }
0N/A
0N/A /**
0N/A * Add all the flags in the given Flags object to this
0N/A * Flags object.
0N/A *
0N/A * @param f Flags object
0N/A */
0N/A public void add(Flags f) {
0N/A system_flags |= f.system_flags; // add system flags
0N/A
0N/A if (f.user_flags != null) { // add user-defined flags
0N/A if (user_flags == null)
787N/A user_flags = new Hashtable<String, String>(1);
0N/A
787N/A Enumeration<String> e = f.user_flags.keys();
0N/A
0N/A while (e.hasMoreElements()) {
787N/A String s = e.nextElement();
0N/A user_flags.put(s, f.user_flags.get(s));
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Remove the specified system flag from this Flags object.
0N/A *
0N/A * @param flag the flag to be removed
0N/A */
0N/A public void remove(Flag flag) {
0N/A system_flags &= ~flag.bit;
0N/A }
0N/A
0N/A /**
0N/A * Remove the specified user flag from this Flags object.
0N/A *
0N/A * @param flag the flag to be removed
0N/A */
0N/A public void remove(String flag) {
0N/A if (user_flags != null)
0N/A user_flags.remove(flag.toLowerCase(Locale.ENGLISH));
0N/A }
0N/A
0N/A /**
0N/A * Remove all flags in the given Flags object from this
0N/A * Flags object.
0N/A *
0N/A * @param f the flag to be removed
0N/A */
0N/A public void remove(Flags f) {
0N/A system_flags &= ~f.system_flags; // remove system flags
0N/A
0N/A if (f.user_flags != null) {
0N/A if (user_flags == null)
0N/A return;
0N/A
787N/A Enumeration<String> e = f.user_flags.keys();
0N/A while (e.hasMoreElements())
0N/A user_flags.remove(e.nextElement());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Check whether the specified system flag is present in this Flags object.
0N/A *
610N/A * @param flag the flag to test
0N/A * @return true of the given flag is present, otherwise false.
0N/A */
0N/A public boolean contains(Flag flag) {
0N/A return (system_flags & flag.bit) != 0;
0N/A }
0N/A
0N/A /**
0N/A * Check whether the specified user flag is present in this Flags object.
0N/A *
610N/A * @param flag the flag to test
0N/A * @return true of the given flag is present, otherwise false.
0N/A */
0N/A public boolean contains(String flag) {
0N/A if (user_flags == null)
0N/A return false;
0N/A else
0N/A return user_flags.containsKey(flag.toLowerCase(Locale.ENGLISH));
0N/A }
0N/A
0N/A /**
0N/A * Check whether all the flags in the specified Flags object are
0N/A * present in this Flags object.
0N/A *
610N/A * @param f the flags to test
0N/A * @return true if all flags in the given Flags object are present,
0N/A * otherwise false.
0N/A */
0N/A public boolean contains(Flags f) {
0N/A // Check system flags
0N/A if ((f.system_flags & system_flags) != f.system_flags)
0N/A return false;
0N/A
0N/A // Check user flags
0N/A if (f.user_flags != null) {
0N/A if (user_flags == null)
0N/A return false;
787N/A Enumeration<String> e = f.user_flags.keys();
0N/A
0N/A while (e.hasMoreElements()) {
0N/A if (!user_flags.containsKey(e.nextElement()))
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A // If we've made it till here, return true
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * Check whether the two Flags objects are equal.
0N/A *
0N/A * @return true if they're equal
0N/A */
0N/A public boolean equals(Object obj) {
0N/A if (!(obj instanceof Flags))
0N/A return false;
0N/A
0N/A Flags f = (Flags)obj;
0N/A
0N/A // Check system flags
0N/A if (f.system_flags != this.system_flags)
0N/A return false;
0N/A
0N/A // Check user flags
0N/A if (f.user_flags == null && this.user_flags == null)
0N/A return true;
0N/A if (f.user_flags != null && this.user_flags != null &&
0N/A f.user_flags.size() == this.user_flags.size()) {
787N/A Enumeration<String> e = f.user_flags.keys();
0N/A
0N/A while (e.hasMoreElements()) {
0N/A if (!this.user_flags.containsKey(e.nextElement()))
0N/A return false;
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Compute a hash code for this Flags object.
0N/A *
0N/A * @return the hash code
0N/A */
0N/A public int hashCode() {
0N/A int hash = system_flags;
0N/A if (user_flags != null) {
787N/A Enumeration<String> e = user_flags.keys();
0N/A while (e.hasMoreElements())
787N/A hash += e.nextElement().hashCode();
0N/A }
0N/A return hash;
0N/A }
0N/A
0N/A /**
0N/A * Return all the system flags in this Flags object. Returns
0N/A * an array of size zero if no flags are set.
0N/A *
0N/A * @return array of Flags.Flag objects representing system flags
0N/A */
0N/A public Flag[] getSystemFlags() {
787N/A Vector<Flag> v = new Vector<Flag>();
0N/A if ((system_flags & ANSWERED_BIT) != 0)
0N/A v.addElement(Flag.ANSWERED);
0N/A if ((system_flags & DELETED_BIT) != 0)
0N/A v.addElement(Flag.DELETED);
0N/A if ((system_flags & DRAFT_BIT) != 0)
0N/A v.addElement(Flag.DRAFT);
0N/A if ((system_flags & FLAGGED_BIT) != 0)
0N/A v.addElement(Flag.FLAGGED);
0N/A if ((system_flags & RECENT_BIT) != 0)
0N/A v.addElement(Flag.RECENT);
0N/A if ((system_flags & SEEN_BIT) != 0)
0N/A v.addElement(Flag.SEEN);
0N/A if ((system_flags & USER_BIT) != 0)
0N/A v.addElement(Flag.USER);
0N/A
0N/A Flag[] f = new Flag[v.size()];
0N/A v.copyInto(f);
0N/A return f;
0N/A }
0N/A
0N/A /**
0N/A * Return all the user flags in this Flags object. Returns
0N/A * an array of size zero if no flags are set.
0N/A *
0N/A * @return array of Strings, each String represents a flag.
0N/A */
0N/A public String[] getUserFlags() {
787N/A Vector<String> v = new Vector<String>();
0N/A if (user_flags != null) {
787N/A Enumeration<String> e = user_flags.elements();
0N/A
0N/A while (e.hasMoreElements())
0N/A v.addElement(e.nextElement());
0N/A }
0N/A
0N/A String[] f = new String[v.size()];
0N/A v.copyInto(f);
0N/A return f;
0N/A }
0N/A
0N/A /**
0N/A * Returns a clone of this Flags object.
0N/A */
787N/A @SuppressWarnings("unchecked")
0N/A public Object clone() {
0N/A Flags f = null;
0N/A try {
0N/A f = (Flags)super.clone();
0N/A } catch (CloneNotSupportedException cex) {
0N/A // ignore, can't happen
0N/A }
464N/A if (this.user_flags != null)
0N/A f.user_flags = (Hashtable)this.user_flags.clone();
0N/A return f;
0N/A }
0N/A
0N/A /*****
0N/A public static void main(String argv[]) throws Exception {
0N/A // a new flags object
0N/A Flags f1 = new Flags();
0N/A f1.add(Flags.Flag.DELETED);
0N/A f1.add(Flags.Flag.SEEN);
0N/A f1.add(Flags.Flag.RECENT);
0N/A f1.add(Flags.Flag.ANSWERED);
0N/A
0N/A // check copy constructor with only system flags
0N/A Flags fc = new Flags(f1);
0N/A if (f1.equals(fc) && fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // check clone with only system flags
0N/A fc = (Flags)f1.clone();
0N/A if (f1.equals(fc) && fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // add a user flag and make sure it still works right
0N/A f1.add("MyFlag");
0N/A
0N/A // shouldn't be equal here
0N/A if (!f1.equals(fc) && !fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // check clone
0N/A fc = (Flags)f1.clone();
0N/A if (f1.equals(fc) && fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // make sure user flag hash tables are separate
0N/A fc.add("AnotherFlag");
0N/A if (!f1.equals(fc) && !fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // check copy constructor
0N/A fc = new Flags(f1);
0N/A if (f1.equals(fc) && fc.equals(f1))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A // another new flags object
0N/A Flags f2 = new Flags(Flags.Flag.ANSWERED);
0N/A f2.add("MyFlag");
0N/A
0N/A if (f1.contains(Flags.Flag.DELETED))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A if (f1.contains(Flags.Flag.SEEN))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A if (f1.contains(Flags.Flag.RECENT))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A if (f1.contains("MyFlag"))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A if (f2.contains(Flags.Flag.ANSWERED))
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A
0N/A System.out.println("----------------");
0N/A
0N/A String[] s = f1.getUserFlags();
0N/A for (int i = 0; i < s.length; i++)
0N/A System.out.println(s[i]);
0N/A System.out.println("----------------");
0N/A s = f2.getUserFlags();
0N/A for (int i = 0; i < s.length; i++)
0N/A System.out.println(s[i]);
0N/A
0N/A System.out.println("----------------");
0N/A
0N/A if (f1.contains(f2)) // this should be true
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A if (!f2.contains(f1)) // this should be false
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A
0N/A Flags f3 = new Flags();
0N/A f3.add(Flags.Flag.DELETED);
0N/A f3.add(Flags.Flag.SEEN);
0N/A f3.add(Flags.Flag.RECENT);
0N/A f3.add(Flags.Flag.ANSWERED);
0N/A f3.add("ANOTHERFLAG");
0N/A f3.add("MYFLAG");
0N/A
0N/A f1.add("AnotherFlag");
0N/A
0N/A if (f1.equals(f3))
0N/A System.out.println("equals success");
0N/A else
0N/A System.out.println("fail");
0N/A if (f3.equals(f1))
0N/A System.out.println("equals success");
0N/A else
0N/A System.out.println("fail");
0N/A System.out.println("f1 hash code " + f1.hashCode());
0N/A System.out.println("f3 hash code " + f3.hashCode());
0N/A if (f1.hashCode() == f3.hashCode())
0N/A System.out.println("success");
0N/A else
0N/A System.out.println("fail");
0N/A }
0N/A ****/
0N/A}