📄 multiplexnewsdb.java
字号:
// MultiplexNewsDb - proxy netnews database
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// Visit the ACME Labs Java page for up-to-date versions of this and other
// fine Java utilities: http://www.acme.com/java/
package Acme.Nnrpd;
import java.io.*;
import java.util.*;
import java.net.*;
import Acme.Utils;
/// Multiplex netnews database.
// <P>
// This is a news database that forwards requests to different sub-databases
// based on the group name.
// <P>
// <A HREF="/resources/classes/Acme/Nnrpd/MultiplexNewsDb.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class MultiplexNewsDb extends NewsDb
{
private Vector groupsPats = new Vector();
private Vector newsDbs = new Vector();
/// The standard overview.fmt. Only if all sub-DBs implement this
// identical format do we do overviewing.
private static String[] overviewFmt = {
"Subject", "From", "Date", "Message-ID", "References", "Bytes",
"Lines" };
/// Constructor.
// @exception NewsDbException if something goes wrong
public MultiplexNewsDb() throws NewsDbException
{
}
/// Add a sub-database for a given pattern of groups.
public void add( String groupsPat, NewsDb newsDb )
{
groupsPats.addElement( groupsPat );
newsDbs.addElement( newsDb );
}
/// Attempt authorization.
// @exception NewsDbException if something goes wrong
public boolean authorize( String user, String password ) throws NewsDbException
{
// If authorization succeeds for all sub-dbs, we return ok.
for ( int i = 0; i < newsDbs.size(); ++i )
{
NewsDb newsDb = (NewsDb) newsDbs.elementAt( i );
if ( ! newsDb.authorize( user, password ) )
return false;
}
return true;
}
/// Whether posting is allowed.
// @exception NewsDbException if something goes wrong
public boolean getPostingOk() throws NewsDbException
{
// This is a guess, really - if posting is ok for any sub-db, we
// return ok.
for ( int i = 0; i < newsDbs.size(); ++i )
{
NewsDb newsDb = (NewsDb) newsDbs.elementAt( i );
if ( newsDb.getPostingOk() )
return true;
}
return false;
}
/// Get a group by name.
// @exception NewsDbException if something goes wrong
public NewsDbGroup getGroup( String groupName ) throws NewsDbException
{
NewsDb newsDb = findNewsDb( groupName );
return newsDb.getGroup( groupName );
}
/// Get an article by group and number.
// @exception NewsDbException if something goes wrong
public NewsDbArticle getArticle( NewsDbGroup group, int artNum ) throws NewsDbException
{
for ( int i = 0; i < newsDbs.size(); ++i )
{
NewsDb newsDb = (NewsDb) newsDbs.elementAt( i );
if ( newsDb.getDbStamp() == group.getDbStamp() )
return newsDb.getArticle( group, artNum );
}
return null;
}
/// Get an article by message-id.
// @exception NewsDbException if something goes wrong
public NewsDbArticle getArticle( String messageId ) throws NewsDbException
{
// This is an even more expensive operation than usual in the
// multiplexing database. Since the dispatching is by group name
// but you don't have a group name, you have to try each sub-db.
for ( int i = 0; i < newsDbs.size(); ++i )
{
NewsDb newsDb = (NewsDb) newsDbs.elementAt( i );
NewsDbArticle article = newsDb.getArticle( messageId );
if ( article != null )
return article;
}
return null;
}
/// Get specified headers from a range of articles by group and number.
// Some implementations have special faster methods for getting
// headers from articles, e.g. an XOVER command to a remote server
// or a local overview database. If no such fast method is available,
// this returns null and the caller should fall back on conventional
// means.
// @exception NewsDbException if something goes wrong
public String[][] getHeaders( String[] names, NewsDbGroup group, int firstArtNum, int lastArtNum ) throws NewsDbException
{
NewsDb newsDb = findNewsDb( group.getName() );
return newsDb.getHeaders( names, group, firstArtNum, lastArtNum );
}
/// Get an enumeration of all the groups.
// @exception NewsDbException if something goes wrong
public Enumeration getGroups() throws NewsDbException
{
return new MultiplexNewsDbGroups( newsDbs.elements() );
}
/// Get an enumeration of all groups created after a given time.
// @exception NewsDbException if something goes wrong
public Enumeration getGroups( long since ) throws NewsDbException
{
return new MultiplexNewsDbGroups( newsDbs.elements(), since );
}
/// Get an enumeration of all groups created after a given time that match
// a given distributions pattern.
// @exception NewsDbException if something goes wrong
public Enumeration getGroups( long since, String distsPat ) throws NewsDbException
{
return new MultiplexNewsDbGroups( newsDbs.elements(), since, distsPat );
}
/// Get an enumeration of all message-ids received after a given time
// in groups matching the given pattern.
// @exception NewsDbException if something goes wrong
public Enumeration getMessageIds( String groupsPat, long since ) throws NewsDbException
{
return new MultiplexNewsDbMessageIds( newsDbs.elements(), groupsPat, since );
}
/// Get an enumeration of all message-ids received after a given time
// in groups matching the given pattern, that also match the
// given distributions pattern.
// @exception NewsDbException if something goes wrong
public Enumeration getMessageIds( String groupsPat, long since, String distsPat ) throws NewsDbException
{
return new MultiplexNewsDbMessageIds( newsDbs.elements(), groupsPat, since, distsPat );
}
/// Post an article.
// @exception NewsDbException if something goes wrong
public void post( String text ) throws NewsDbException
{
// Find the newsgroups line in the article and parse it to
// find a group, then post to the right db for that group.
String newsgroups = NewsDbArticle.getHeader( text, "Newsgroups" );
if ( newsgroups == null || newsgroups.length() == 0 )
throw new NewsDbException( "article has no newsgroups" );
StringTokenizer st = new StringTokenizer( newsgroups, "," );
while ( st.hasMoreTokens() )
{
String groupName = st.nextToken();
NewsDb newsDb;
try
{
newsDb = findNewsDb( groupName );
}
catch ( NewsDbException e )
{
// Try another group.
continue;
}
newsDb.post( text );
return;
}
throw new NewsDbException(
"can't find a news database supporting any group in " +
newsgroups );
}
/// Shut down the news database.
public void close()
{
for ( int i = 0; i < newsDbs.size(); ++i )
{
NewsDb newsDb = (NewsDb) newsDbs.elementAt( i );
newsDb.close();
}
newsDbs = null;
}
/// Find the sub-database for a given group.
private NewsDb findNewsDb( String groupName ) throws NewsDbException
{
for ( int i = 0; i < groupsPats.size(); ++i )
{
String groupsPat = (String) groupsPats.elementAt( i );
if ( Utils.match( groupsPat, groupName ) )
return (NewsDb) newsDbs.elementAt( i );
}
throw new NewsDbException( "no database found for group " + groupName );
}
}
class MultiplexNewsDbGroups implements Enumeration
{
private Enumeration dbEnum;
private long since;
private String distsPat;
private Enumeration groupEnum;
private NewsDbGroup group;
public MultiplexNewsDbGroups( Enumeration dbEnum )
{
this( dbEnum, -1, null );
}
public MultiplexNewsDbGroups( Enumeration dbEnum, long since )
{
this( dbEnum, since, null );
}
public MultiplexNewsDbGroups( Enumeration dbEnum, long since, String distsPat )
{
this.dbEnum = dbEnum;
this.since = since;
this.distsPat = distsPat;
groupEnum = null;
group = null;
}
public boolean hasMoreElements()
{
if ( group != null )
return true;
while ( true )
{
if ( groupEnum == null )
{
if ( dbEnum == null )
return false;
if ( ! dbEnum.hasMoreElements() )
{
dbEnum = null;
return false;
}
try
{
NewsDb db = (NewsDb) dbEnum.nextElement();
if ( since != -1 && distsPat != null )
groupEnum = db.getGroups( since, distsPat );
else if ( since != -1 )
groupEnum = db.getGroups( since );
else
groupEnum = db.getGroups();
}
catch ( NewsDbException e )
{
continue;
}
}
if ( ! groupEnum.hasMoreElements() )
{
groupEnum = null;
continue;
}
group = (NewsDbGroup) groupEnum.nextElement();
return true;
}
}
public Object nextElement()
{
if ( ! hasMoreElements() )
return null;
NewsDbGroup g = group;
group = null;
return g;
}
}
class MultiplexNewsDbMessageIds implements Enumeration
{
private Enumeration dbEnum;
private String groupsPat;
private long since;
private String distsPat;
private Enumeration messageIdEnum;
private String messageId;
public MultiplexNewsDbMessageIds( Enumeration dbEnum, String groupsPat, long since )
{
this( dbEnum, groupsPat, since, null );
}
public MultiplexNewsDbMessageIds( Enumeration dbEnum, String groupsPat, long since, String distsPat )
{
this.dbEnum = dbEnum;
this.groupsPat = groupsPat;
this.since = since;
this.distsPat = distsPat;
messageIdEnum = null;
messageId = null;
}
public boolean hasMoreElements()
{
if ( messageId != null )
return true;
while ( true )
{
if ( messageIdEnum == null )
{
if ( dbEnum == null )
return false;
if ( ! dbEnum.hasMoreElements() )
{
dbEnum = null;
return false;
}
try
{
NewsDb db = (NewsDb) dbEnum.nextElement();
if ( distsPat != null )
messageIdEnum = db.getMessageIds( groupsPat, since, distsPat );
else
messageIdEnum = db.getMessageIds( groupsPat, since );
}
catch ( NewsDbException e )
{
continue;
}
}
if ( ! messageIdEnum.hasMoreElements() )
{
messageIdEnum = null;
continue;
}
messageId = (String) messageIdEnum.nextElement();
return true;
}
}
public Object nextElement()
{
if ( ! hasMoreElements() )
return null;
String mid = messageId;
messageId = null;
return mid;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -