Source Code Cross Referenced for NNTPRepositoryImpl.java in  » Web-Mail » james-2.3.1 » org » apache » james » nntpserver » repository » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Mail » james 2.3.1 » org.apache.james.nntpserver.repository 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:         ****************************************************************/package org.apache.james.nntpserver.repository;
019:
020:        import org.apache.avalon.framework.activity.Initializable;
021:        import org.apache.avalon.framework.configuration.Configurable;
022:        import org.apache.avalon.framework.configuration.Configuration;
023:        import org.apache.avalon.framework.configuration.ConfigurationException;
024:        import org.apache.avalon.framework.container.ContainerUtil;
025:        import org.apache.avalon.framework.context.Context;
026:        import org.apache.avalon.framework.context.ContextException;
027:        import org.apache.avalon.framework.context.Contextualizable;
028:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
029:        import org.apache.james.context.AvalonContextUtilities;
030:        import org.apache.james.nntpserver.DateSinceFileFilter;
031:        import org.apache.james.nntpserver.NNTPException;
032:        import org.apache.james.util.io.AndFileFilter;
033:        import org.apache.james.util.io.DirectoryFileFilter;
034:        import org.apache.oro.io.GlobFilenameFilter;
035:
036:        import java.io.File;
037:        import java.io.FileOutputStream;
038:        import java.io.InputStream;
039:        import java.io.IOException;
040:        import java.util.ArrayList;
041:        import java.util.Date;
042:        import java.util.HashMap;
043:        import java.util.Iterator;
044:        import java.util.List;
045:        import java.util.Set;
046:
047:        /**
048:         * NNTP Repository implementation.
049:         */
050:        public class NNTPRepositoryImpl extends AbstractLogEnabled implements 
051:                NNTPRepository, Contextualizable, Configurable, Initializable {
052:
053:            /**
054:             * The context employed by this repository
055:             */
056:            private Context context;
057:
058:            /**
059:             * The configuration employed by this repository
060:             */
061:            private Configuration configuration;
062:
063:            /**
064:             * Whether the repository is read only
065:             */
066:            private boolean readOnly;
067:
068:            /**
069:             * The groups are located under this path.
070:             */
071:            private File rootPath;
072:
073:            /**
074:             * Articles are temporarily written here and then sent to the spooler.
075:             */
076:            private File tempPath;
077:
078:            /**
079:             * The spooler for this repository.
080:             */
081:            private NNTPSpooler spool;
082:
083:            /**
084:             * The article ID repository associated with this NNTP repository.
085:             */
086:            private ArticleIDRepository articleIDRepo;
087:
088:            /**
089:             * A map to allow lookup of valid newsgroup names
090:             */
091:            private HashMap groupNameMap = null;
092:
093:            /**
094:             * Restrict use to newsgroups specified in config only
095:             */
096:            private boolean definedGroupsOnly = false;
097:
098:            /**
099:             * The root path as a String.
100:             */
101:            private String rootPathString = null;
102:
103:            /**
104:             * The temp path as a String.
105:             */
106:            private String tempPathString = null;
107:
108:            /**
109:             * The article ID path as a String.
110:             */
111:            private String articleIdPathString = null;
112:
113:            /**
114:             * The domain suffix used for files in the article ID repository.
115:             */
116:            private String articleIDDomainSuffix = null;
117:
118:            /**
119:             * The ordered list of fields returned in the overview format for
120:             * articles stored in this repository.
121:             */
122:            private String[] overviewFormat = { "Subject:", "From:", "Date:",
123:                    "Message-ID:", "References:", "Bytes:", "Lines:" };
124:
125:            /**
126:             * This is a mapping of group names to NNTP group objects.
127:             *
128:             * TODO: This needs to be addressed so it scales better
129:             */
130:            private HashMap repositoryGroups = new HashMap();
131:
132:            /**
133:             * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
134:             */
135:            public void contextualize(Context context) throws ContextException {
136:                this .context = context;
137:            }
138:
139:            /**
140:             * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
141:             */
142:            public void configure(Configuration aConfiguration)
143:                    throws ConfigurationException {
144:                configuration = aConfiguration;
145:                readOnly = configuration.getChild("readOnly")
146:                        .getValueAsBoolean(false);
147:                articleIDDomainSuffix = configuration.getChild(
148:                        "articleIDDomainSuffix").getValue("foo.bar.sho.boo");
149:                rootPathString = configuration.getChild("rootPath").getValue(
150:                        null);
151:                if (rootPathString == null) {
152:                    throw new ConfigurationException(
153:                            "Root path URL is required.");
154:                }
155:                tempPathString = configuration.getChild("tempPath").getValue(
156:                        null);
157:                if (tempPathString == null) {
158:                    throw new ConfigurationException(
159:                            "Temp path URL is required.");
160:                }
161:                articleIdPathString = configuration.getChild("articleIDPath")
162:                        .getValue(null);
163:                if (articleIdPathString == null) {
164:                    throw new ConfigurationException(
165:                            "Article ID path URL is required.");
166:                }
167:                if (getLogger().isDebugEnabled()) {
168:                    if (readOnly) {
169:                        getLogger().debug("NNTP repository is read only.");
170:                    } else {
171:                        getLogger().debug("NNTP repository is writeable.");
172:                    }
173:                    getLogger().debug(
174:                            "NNTP repository root path URL is "
175:                                    + rootPathString);
176:                    getLogger().debug(
177:                            "NNTP repository temp path URL is "
178:                                    + tempPathString);
179:                    getLogger().debug(
180:                            "NNTP repository article ID path URL is "
181:                                    + articleIdPathString);
182:                }
183:                Configuration newsgroupConfiguration = configuration
184:                        .getChild("newsgroups");
185:                definedGroupsOnly = newsgroupConfiguration
186:                        .getAttributeAsBoolean("only", false);
187:                groupNameMap = new HashMap();
188:                if (newsgroupConfiguration != null) {
189:                    Configuration[] children = newsgroupConfiguration
190:                            .getChildren("newsgroup");
191:                    if (children != null) {
192:                        for (int i = 0; i < children.length; i++) {
193:                            String groupName = children[i].getValue();
194:                            groupNameMap.put(groupName, groupName);
195:                        }
196:                    }
197:                }
198:                getLogger().debug("Repository configuration done");
199:            }
200:
201:            /**
202:             * @see org.apache.avalon.framework.activity.Initializable#initialize()
203:             */
204:            public void initialize() throws Exception {
205:
206:                getLogger().debug("Starting initialize");
207:                File articleIDPath = null;
208:
209:                try {
210:                    rootPath = AvalonContextUtilities.getFile(context,
211:                            rootPathString);
212:                    tempPath = AvalonContextUtilities.getFile(context,
213:                            tempPathString);
214:                    articleIDPath = AvalonContextUtilities.getFile(context,
215:                            articleIdPathString);
216:                } catch (Exception e) {
217:                    getLogger().fatalError(e.getMessage(), e);
218:                    throw e;
219:                }
220:
221:                if (articleIDPath.exists() == false) {
222:                    articleIDPath.mkdirs();
223:                }
224:
225:                articleIDRepo = new ArticleIDRepository(articleIDPath,
226:                        articleIDDomainSuffix);
227:                spool = (NNTPSpooler) createSpooler();
228:                spool.setRepository(this );
229:                spool.setArticleIDRepository(articleIDRepo);
230:                if (getLogger().isDebugEnabled()) {
231:                    getLogger().debug("repository:readOnly=" + readOnly);
232:                    getLogger()
233:                            .debug(
234:                                    "repository:rootPath="
235:                                            + rootPath.getAbsolutePath());
236:                    getLogger()
237:                            .debug(
238:                                    "repository:tempPath="
239:                                            + tempPath.getAbsolutePath());
240:                }
241:
242:                if (rootPath.exists() == false) {
243:                    rootPath.mkdirs();
244:                } else if (!(rootPath.isDirectory())) {
245:                    StringBuffer errorBuffer = new StringBuffer(128)
246:                            .append(
247:                                    "NNTP repository root directory is improperly configured.  The specified path ")
248:                            .append(rootPathString).append(
249:                                    " is not a directory.");
250:                    throw new ConfigurationException(errorBuffer.toString());
251:                }
252:
253:                Set groups = groupNameMap.keySet();
254:                Iterator groupIterator = groups.iterator();
255:                while (groupIterator.hasNext()) {
256:                    String groupName = (String) groupIterator.next();
257:                    File groupFile = new File(rootPath, groupName);
258:                    if (groupFile.exists() == false) {
259:                        groupFile.mkdirs();
260:                    } else if (!(groupFile.isDirectory())) {
261:                        StringBuffer errorBuffer = new StringBuffer(128)
262:                                .append(
263:                                        "A file exists in the NNTP root directory with the same name as a newsgroup.  File ")
264:                                .append(groupName).append("in directory ")
265:                                .append(rootPathString).append(
266:                                        " is not a directory.");
267:                        throw new ConfigurationException(errorBuffer.toString());
268:                    }
269:                }
270:                if (tempPath.exists() == false) {
271:                    tempPath.mkdirs();
272:                } else if (!(tempPath.isDirectory())) {
273:                    StringBuffer errorBuffer = new StringBuffer(128)
274:                            .append(
275:                                    "NNTP repository temp directory is improperly configured.  The specified path ")
276:                            .append(tempPathString).append(
277:                                    " is not a directory.");
278:                    throw new ConfigurationException(errorBuffer.toString());
279:                }
280:
281:                getLogger().debug("repository initialization done");
282:            }
283:
284:            /**
285:             * @see org.apache.james.nntpserver.repository.NNTPRepository#isReadOnly()
286:             */
287:            public boolean isReadOnly() {
288:                return readOnly;
289:            }
290:
291:            /**
292:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getGroup(String)
293:             */
294:            public NNTPGroup getGroup(String groupName) {
295:                if (definedGroupsOnly && groupNameMap.get(groupName) == null) {
296:                    if (getLogger().isDebugEnabled()) {
297:                        getLogger()
298:                                .debug(
299:                                        groupName
300:                                                + " is not a newsgroup hosted on this server.");
301:                    }
302:                    return null;
303:                }
304:                File groupFile = new File(rootPath, groupName);
305:                NNTPGroup groupToReturn = null;
306:                synchronized (this ) {
307:                    groupToReturn = (NNTPGroup) repositoryGroups.get(groupName);
308:                    if ((groupToReturn == null) && groupFile.exists()
309:                            && groupFile.isDirectory()) {
310:                        try {
311:                            groupToReturn = new NNTPGroupImpl(groupFile);
312:                            ContainerUtil.enableLogging(groupToReturn,
313:                                    getLogger());
314:                            ContainerUtil.contextualize(groupToReturn, context);
315:                            ContainerUtil.initialize(groupToReturn);
316:                            repositoryGroups.put(groupName, groupToReturn);
317:                        } catch (Exception e) {
318:                            getLogger().error("Couldn't create group object.",
319:                                    e);
320:                            groupToReturn = null;
321:                        }
322:                    }
323:                }
324:                return groupToReturn;
325:            }
326:
327:            /**
328:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getArticleFromID(String)
329:             */
330:            public NNTPArticle getArticleFromID(String id) {
331:                try {
332:                    return articleIDRepo.getArticle(this , id);
333:                } catch (Exception ex) {
334:                    getLogger().error("Couldn't get article " + id + ": ", ex);
335:                    return null;
336:                }
337:            }
338:
339:            /**
340:             * @see org.apache.james.nntpserver.repository.NNTPRepository#createArticle(InputStream)
341:             */
342:            public void createArticle(InputStream in) {
343:                StringBuffer fileBuffer = new StringBuffer(32).append(
344:                        System.currentTimeMillis()).append(".").append(
345:                        Math.random());
346:                File f = new File(tempPath, fileBuffer.toString());
347:                FileOutputStream fout = null;
348:                try {
349:                    fout = new FileOutputStream(f);
350:                    byte[] readBuffer = new byte[1024];
351:                    int bytesRead = 0;
352:                    while ((bytesRead = in.read(readBuffer, 0, 1024)) > 0) {
353:                        fout.write(readBuffer, 0, bytesRead);
354:                    }
355:                    fout.flush();
356:                    fout.close();
357:                    fout = null;
358:                    boolean renamed = f.renameTo(new File(spool.getSpoolPath(),
359:                            f.getName()));
360:                    if (!renamed) {
361:                        throw new IOException(
362:                                "Could not create article on the spool.");
363:                    }
364:                } catch (IOException ex) {
365:                    throw new NNTPException("create article failed", ex);
366:                } finally {
367:                    if (fout != null) {
368:                        try {
369:                            fout.close();
370:                        } catch (IOException ioe) {
371:                            // Ignored
372:                        }
373:                    }
374:                }
375:            }
376:
377:            class GroupFilter implements  java.io.FilenameFilter {
378:                public boolean accept(java.io.File dir, String name) {
379:                    if (getLogger().isDebugEnabled()) {
380:                        getLogger()
381:                                .debug(
382:                                        ((definedGroupsOnly ? groupNameMap
383:                                                .containsKey(name) : true) ? "Accepting "
384:                                                : "Rejecting")
385:                                                + name);
386:                    }
387:
388:                    return definedGroupsOnly ? groupNameMap.containsKey(name)
389:                            : true;
390:                }
391:            }
392:
393:            /**
394:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getMatchedGroups(String)
395:             */
396:            public Iterator getMatchedGroups(String wildmat) {
397:                File[] f = rootPath.listFiles(new AndFileFilter(
398:                        new GroupFilter(), new AndFileFilter(
399:                                new DirectoryFileFilter(),
400:                                new GlobFilenameFilter(wildmat))));
401:                return getGroups(f);
402:            }
403:
404:            /**
405:             * Gets an iterator of all news groups represented by the files
406:             * in the parameter array.
407:             *
408:             * @param f the array of files that correspond to news groups
409:             *
410:             * @return an iterator of news groups
411:             */
412:            private Iterator getGroups(File[] f) {
413:                List list = new ArrayList();
414:                for (int i = 0; i < f.length; i++) {
415:                    if (f[i] != null) {
416:                        list.add(getGroup(f[i].getName()));
417:                    }
418:                }
419:                return list.iterator();
420:            }
421:
422:            /**
423:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getGroupsSince(Date)
424:             */
425:            public Iterator getGroupsSince(Date dt) {
426:                File[] f = rootPath.listFiles(new AndFileFilter(
427:                        new GroupFilter(), new AndFileFilter(
428:                                new DirectoryFileFilter(),
429:                                new DateSinceFileFilter(dt.getTime()))));
430:                return getGroups(f);
431:            }
432:
433:            // gets the list of groups.
434:            // creates iterator that concatenates the article iterators in the list of groups.
435:            // there is at most one article iterator reference for all the groups
436:
437:            /**
438:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getArticlesSince(Date)
439:             */
440:            public Iterator getArticlesSince(final Date dt) {
441:                final Iterator giter = getGroupsSince(dt);
442:                return new Iterator() {
443:
444:                    private Iterator iter = null;
445:
446:                    public boolean hasNext() {
447:                        if (iter == null) {
448:                            if (giter.hasNext()) {
449:                                NNTPGroup group = (NNTPGroup) giter.next();
450:                                iter = group.getArticlesSince(dt);
451:                            } else {
452:                                return false;
453:                            }
454:                        }
455:                        if (iter.hasNext()) {
456:                            return true;
457:                        } else {
458:                            iter = null;
459:                            return hasNext();
460:                        }
461:                    }
462:
463:                    public Object next() {
464:                        return iter.next();
465:                    }
466:
467:                    public void remove() {
468:                        throw new UnsupportedOperationException(
469:                                "remove not supported");
470:                    }
471:                };
472:            }
473:
474:            /**
475:             * @see org.apache.james.nntpserver.repository.NNTPRepository#getOverviewFormat()
476:             */
477:            public String[] getOverviewFormat() {
478:                return overviewFormat;
479:            }
480:
481:            /**
482:             * Creates an instance of the spooler class.
483:             *
484:             * TODO: This method doesn't properly implement the Avalon lifecycle.
485:             */
486:            private NNTPSpooler createSpooler() throws ConfigurationException {
487:                String className = "org.apache.james.nntpserver.repository.NNTPSpooler";
488:                Configuration spoolerConfiguration = configuration
489:                        .getChild("spool");
490:                try {
491:                    // Must be a subclass of org.apache.james.nntpserver.repository.NNTPSpooler
492:                    className = spoolerConfiguration.getAttribute("class");
493:                } catch (ConfigurationException ce) {
494:                    // Use the default class.
495:                }
496:                try {
497:                    Object obj = getClass().getClassLoader().loadClass(
498:                            className).newInstance();
499:                    // TODO: Need to support service
500:                    ContainerUtil.enableLogging(obj, getLogger());
501:                    ContainerUtil.contextualize(obj, context);
502:                    ContainerUtil.configure(obj, spoolerConfiguration
503:                            .getChild("configuration"));
504:                    ContainerUtil.initialize(obj);
505:                    return (NNTPSpooler) obj;
506:                } catch (ClassCastException cce) {
507:                    StringBuffer errorBuffer = new StringBuffer(128)
508:                            .append(
509:                                    "Spooler initialization failed because the spooler class ")
510:                            .append(className)
511:                            .append(
512:                                    " was not a subclass of org.apache.james.nntpserver.repository.NNTPSpooler");
513:                    String errorString = errorBuffer.toString();
514:                    getLogger().error(errorString, cce);
515:                    throw new ConfigurationException(errorString, cce);
516:                } catch (Exception ex) {
517:                    getLogger().error("Spooler initialization failed", ex);
518:                    throw new ConfigurationException(
519:                            "Spooler initialization failed", ex);
520:                }
521:            }
522:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.