KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > nntpserver > repository > ArticleIDRepository


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.nntpserver.repository;
19
20 import org.apache.james.util.Base64;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.util.Date;
27 import java.util.Enumeration;
28 import java.util.Properties;
29
30 /**
31  * ArticleIDRepository: contains one file for each article.
32  * the file name is Base64 encoded article ID
33  * The first line of the file is '# <create date of file>
34  * the rest of line have <newsgroup name>=<article number>
35  * Allows fast lookup of a message by message id.
36  *
37  * This class allows a process to iterate and synchronize messages with other NNTP Servers.
38  * This may be inefficient. It may be better to use an alternate, more
39  * efficient process for synchronization and this class for sanity check.
40  *
41  */

42 public class ArticleIDRepository {
43
44     /**
45      * The root of the repository in the file system
46      */

47     private final File root;
48
49     /**
50      * The suffix appended to the articleIDs
51      */

52     private final String articleIDDomainSuffix;
53
54     /**
55      * A counter of the number of article IDs
56      *
57      * TODO: Potentially serious threading problem here
58      */

59     private int counter = 0;
60
61     ArticleIDRepository(File root,String articleIDDomainSuffix) {
62         this.root = root;
63         this.articleIDDomainSuffix = articleIDDomainSuffix;
64     }
65
66     /**
67      * Generate a new article ID for use in the repository.
68      */

69     String generateArticleID() {
70         int idx = Math.abs(counter++);
71         StringBuffer idBuffer =
72             new StringBuffer(256)
73                     .append("<")
74                     .append(Thread.currentThread().hashCode())
75                     .append(".")
76                     .append(System.currentTimeMillis())
77                     .append(".")
78                     .append(idx)
79                     .append("@")
80                     .append(articleIDDomainSuffix)
81                     .append(">");
82         return idBuffer.toString();
83     }
84
85     /**
86      * Add the article information to the repository.
87      *
88      * @param prop contains the newsgroup name and article number.
89      */

90     void addArticle(String articleID,Properties prop) throws IOException {
91         if ( articleID == null ) {
92             articleID = generateArticleID();
93         }
94         FileOutputStream fout = null;
95         try {
96             fout = new FileOutputStream(getFileFromID(articleID));
97             prop.store(fout,new Date().toString());
98         } finally {
99             if (fout != null) {
100                 fout.close();
101             }
102         }
103     }
104
105     /**
106      * Returns the file in the repository corresponding to the specified
107      * article ID.
108      *
109      * @param articleID the article ID
110      *
111      * @return the repository file
112      */

113     File getFileFromID(String articleID) {
114         String b64Id;
115         try {
116             b64Id = removeCRLF(Base64.encodeAsString(articleID));
117         } catch (Exception e) {
118             throw new RuntimeException("This shouldn't happen: " + e);
119         }
120         return new File(root, b64Id);
121     }
122
123     /**
124      * the base64 encode from javax.mail.internet.MimeUtility adds line
125      * feeds to the encoded stream. This removes them, since we will
126      * use the String as a filename.
127      */

128     private static String removeCRLF(String str) {
129         StringBuffer buffer = new StringBuffer();
130         for (int i = 0; i < str.length(); i++) {
131             char c = str.charAt(i);
132             if (c != '\r' && c != '\n') {
133                 buffer.append(c);
134             }
135         }
136         return buffer.toString();
137     }
138
139     /**
140      * Returns whether the article ID is in the repository
141      *
142      * @param articleID the article ID
143      *
144      * @return whether the article ID is in the repository
145      */

146     boolean isExists(String articleID) {
147         return ( articleID == null ) ? false : getFileFromID(articleID).exists();
148     }
149
150     /**
151      * Get the article from the NNTP respository with the specified id.
152      *
153      * @param repo the NNTP repository where the article is stored
154      * @param id the id of the article to retrieve
155      *
156      * @return the article
157      *
158      * @throws IOException if the ID information cannot be loaded
159      */

160     NNTPArticle getArticle(NNTPRepository repo,String id) throws IOException {
161         File f = getFileFromID(id);
162         if ( f.exists() == false ) {
163             return null;
164         }
165         FileInputStream fin = null;
166         Properties prop = new Properties();
167         try {
168             fin = new FileInputStream(f);
169             prop.load(fin);
170         } finally {
171             if (fin != null) {
172                 fin.close();
173             }
174         }
175         Enumeration enum = prop.keys();
176         NNTPArticle article = null;
177         while ( article == null && enum.hasMoreElements() ) {
178             String groupName = (String)enum.nextElement();
179             int number = Integer.parseInt(prop.getProperty(groupName));
180             NNTPGroup group = repo.getGroup(groupName);
181             if ( group != null ) {
182                 article = group.getArticle(number);
183             }
184         }
185         return article;
186     }
187 }
188
Popular Tags