001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.geronimo.javamail.store.nntp;
021
022 import java.io.File;
023 import java.io.PrintStream;
024 import java.util.Iterator;
025
026 import javax.mail.Folder;
027 import javax.mail.MessagingException;
028 import javax.mail.Session;
029 import javax.mail.Store;
030 import javax.mail.URLName;
031
032 import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrc;
033 import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcFile;
034 import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
035 import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
036 import org.apache.geronimo.javamail.util.ProtocolProperties;
037 import org.apache.geronimo.mail.util.SessionUtil;
038
039 /**
040 * NNTP implementation of javax.mail.Store POP protocol spec is implemented in
041 * org.apache.geronimo.javamail.store.pop3.NNTPConnection
042 *
043 * @version $Rev: 673152 $ $Date: 2008-07-01 13:37:38 -0400 (Tue, 01 Jul 2008) $
044 */
045 public class NNTPStore extends Store {
046 protected static final String NNTP_NEWSRC = "newsrc";
047
048 protected static final String protocol = "nntp";
049
050 protected static final int DEFAULT_NNTP_PORT = 119;
051 protected static final int DEFAULT_NNTP_SSL_PORT = 563;
052
053 // our accessor for protocol properties and the holder of
054 // protocol-specific information
055 protected ProtocolProperties props;
056 // our active connection object (shared code with the NNTPStore).
057 protected NNTPConnection connection;
058
059 // the root folder
060 protected NNTPRootFolder root;
061 // the newsrc file where we store subscriptions and seen message markers.
062 protected NNTPNewsrc newsrc;
063
064 /**
065 * Construct an NNTPStore item. This will load the .newsrc file associated
066 * with the server.
067 *
068 * @param session
069 * The owning javamail Session.
070 * @param name
071 * The Store urlName, which can contain server target
072 * information.
073 */
074 public NNTPStore(Session session, URLName name) {
075 this(session, name, "nntp", DEFAULT_NNTP_PORT, false);
076 }
077
078 /**
079 * Common constructor used by the POP3Store and POP3SSLStore classes
080 * to do common initialization of defaults.
081 *
082 * @param session
083 * The host session instance.
084 * @param name
085 * The URLName of the target.
086 * @param protocol
087 * The protocol type ("nntp" or "nntps"). This helps us in
088 * retrieving protocol-specific session properties.
089 * @param defaultPort
090 * The default port used by this protocol. For pop3, this will
091 * be 110. The default for pop3 with ssl is 995.
092 * @param sslConnection
093 * Indicates whether an SSL connection should be used to initial
094 * contact the server. This is different from the STARTTLS
095 * support, which switches the connection to SSL after the
096 * initial startup.
097 */
098 protected NNTPStore(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
099 super(session, name);
100
101 // create the protocol property holder. This gives an abstraction over the different
102 // flavors of the protocol.
103 props = new ProtocolProperties(session, protocol, sslConnection, defaultPort);
104
105 // the connection manages connection for the transport
106 connection = new NNTPConnection(props);
107 }
108
109 /**
110 * @see javax.mail.Store#getDefaultFolder()
111 *
112 * This returns a root folder object for all of the news groups.
113 */
114 public Folder getDefaultFolder() throws MessagingException {
115 checkConnectionStatus();
116 if (root == null) {
117 return new NNTPRootFolder(this, connection.getHost(), connection.getWelcomeString());
118 }
119 return root;
120 }
121
122 /**
123 * @see javax.mail.Store#getFolder(java.lang.String)
124 */
125 public Folder getFolder(String name) throws MessagingException {
126 return getDefaultFolder().getFolder(name);
127 }
128
129 /**
130 *
131 * @see javax.mail.Store#getFolder(javax.mail.URLName)
132 */
133 public Folder getFolder(URLName url) throws MessagingException {
134 return getDefaultFolder().getFolder(url.getFile());
135 }
136
137
138 /**
139 * Do the protocol connection for an NNTP transport. This handles server
140 * authentication, if possible. Returns false if unable to connect to the
141 * server.
142 *
143 * @param host
144 * The target host name.
145 * @param port
146 * The server port number.
147 * @param user
148 * The authentication user (if any).
149 * @param password
150 * The server password. Might not be sent directly if more
151 * sophisticated authentication is used.
152 *
153 * @return true if we were able to connect to the server properly, false for
154 * any failures.
155 * @exception MessagingException
156 */
157 protected boolean protocolConnect(String host, int port, String username, String password)
158 throws MessagingException {
159 // the connection pool handles all of the details here. But don't proceed
160 // without a connection
161 if (!connection.protocolConnect(host, port, username, password)) {
162 return false;
163 }
164
165 // see if we have a newsrc file location specified
166 String newsrcFile = props.getProperty(NNTP_NEWSRC);
167
168 File source = null;
169
170 // not given as a property? Then look for a file in user.home
171 if (newsrcFile != null) {
172 source = new File(newsrcFile);
173 } else {
174 // ok, look for a file in the user.home directory. If possible,
175 // we'll try for a file
176 // with the hostname appended.
177 String home = SessionUtil.getProperty("user.home");
178
179 // try for a host-specific file first. If not found, use (and
180 // potentially create) a generic
181 // .newsrc file.
182 newsrcFile = ".newsrc-" + host;
183 source = new File(home, newsrcFile);
184 if (!source.exists()) {
185 source = new File(home, ".newsrc");
186 }
187 }
188
189 // now create a newsrc read and load the file.
190 newsrc = new NNTPNewsrcFile(source);
191 newsrc.load();
192
193 // we're going to return success here, but in truth, the server may end
194 // up asking for our bonafides at any time, and we'll be expected to authenticate then.
195 return true;
196 }
197
198
199 /**
200 * @see javax.mail.Service#close()
201 */
202 public void close() throws MessagingException {
203 // This is done to ensure proper event notification.
204 super.close();
205 // persist the newsrc file, if possible
206 if (newsrc != null) {
207 newsrc.close();
208 newsrc = null;
209 }
210 connection.close();
211 connection = null;
212 }
213
214 private void checkConnectionStatus() throws MessagingException {
215 if (!this.isConnected()) {
216 throw new MessagingException("Not connected ");
217 }
218 }
219
220 /**
221 * Retrieve the server connection created by this store.
222 *
223 * @return The active connection object.
224 */
225 NNTPConnection getConnection() {
226 return connection;
227 }
228
229 /**
230 * Retrieve the Session object this Store is operating under.
231 *
232 * @return The attached Session instance.
233 */
234 Session getSession() {
235 return session;
236 }
237
238 /**
239 * Retrieve all of the groups we nave persistent store information about.
240 *
241 * @return The set of groups contained in the newsrc file.
242 */
243 Iterator getNewsrcGroups() {
244 return newsrc.getGroups();
245 }
246
247 /**
248 * Retrieve the newsrc group information for a named group. If the file does
249 * not currently include this group, an unsubscribed group will be added to
250 * the file.
251 *
252 * @param name
253 * The name of the target group.
254 *
255 * @return The NNTPNewsrcGroup item corresponding to this name.
256 */
257 NNTPNewsrcGroup getNewsrcGroup(String name) {
258 return newsrc.getGroup(name);
259 }
260 }