📄 cm.java
字号:
/*
*
* $Id: Cm.java,v 1.84 2002/06/05 22:23:51 hamada Exp $
*
* Copyright (c) 2001 Sun Microsystems, Inc. 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.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Sun Microsystems, Inc. for Project JXTA."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact Project JXTA at http://www.jxta.org.
*
* 5. Products derived from this software may not be called "JXTA",
* nor may "JXTA" appear in their name, without prior written
* permission of Sun.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 SUN MICROSYSTEMS OR
* ITS 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.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Project JXTA. For more
* information on Project JXTA, please see
* <http://www.jxta.org/>.
*
* This license is based on the BSD license adopted by the Apache Foundation.
* $Id: Cm.java,v 1.84 2002/06/05 22:23:51 hamada Exp $
*/
package net.jxta.impl.cm;
import java.io.File;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.ResourceBundle;
import java.util.Random;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.MissingResourceException;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.Element;
import net.jxta.document.MimeMediaType;
import net.jxta.document.StructuredDocumentFactory;
import net.jxta.document.StructuredDocument;
import net.jxta.document.StructuredTextDocument;
import net.jxta.impl.config.Config;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
/**
* This class implements a limited document caching mechanism
* intended to provide cache for services that have a need for cache
* to search and exchange jxta documents.
*
* Only Core Services are intended to use this mechanism.
*
*/
public final class Cm {
/**
* the name we will use for the base directory
*
* @since 1.0
*/
public final static String RootDirBase = Config.JXTA_HOME + "cm";
/**
* The name we will use for the public cm contents
*
* @since 1.0
*/
public final static String PublicDirName = "public";
/**
* The name we will use for the private cm contents
*
* @since 1.0
*/
public final static String PrivateDirName = "private";
/**
* The name we will use for temp cm contents
*
* @since 1.0
*/
public final static String TmpDirName = "tmp";
/**
* The Log4J debugging category.
*
* @since 1.0
*/
private final static Category LOG = Category.getInstance(Cm.class.getName());
/**
* Random number generator used for file name generation
*
* @since 1.0
*/
private final static Random random = new Random();
/**
* SchedulerService for use by FileExpirationService instances.
*/
protected final static SchedulerService schedulerService =
new SchedulerService();
/**
*Description of the Field
*
* @since 1.0
*/
protected Hashtable indexes = new Hashtable(4);
protected Hashtable caches = new Hashtable(4);
/**
* file descriptor for the root of the cm
*
* @since 1.0
*/
protected File rootDir;
/**
* file expiration service used by this cm instance
*
* @since 1.0
*/
private FileExpirationService expirer;
/*
* default index filename for each cm dir
*/
private String INDEXFILENAME = "cm.idx";
private static final int RAW = 0;
private static final int CACHE = 1;
private static final int INDEX = 2;
private int searchMethod = RAW;
private String [] searchType = {"RAW","CACHE","INDEX"};
ExpirationListener expireListener;
/**
* Start the SchedulerService.
*/
static {
new Thread(schedulerService, "SchedulerService").start();
}
/**
* Expiration Listener Interface
*
*/
public interface ExpirationListener {
/**
*
* Expiration event
*
* @param file the file which is expiring
* @return true if the file should be deleted.
*/
public boolean expired( File file );
}
/**
* standard constructor for a cm
*
* @param areaName the name of the cm sub-dir to create
* @param enableOptimize whether to enable indexing
* @since 1.0
*/
public Cm(String areaName, boolean enableOptimize) {
this( areaName, new Cm.ExpirationListener() {
public boolean expired( File file ) {
return true; // yep, its dead.
}
}, enableOptimize );
}
/**
* constructor for cm with expirations listener
*
* @param areaName the name of the cm sub-dir to create
* @param listener a listener that will be called back when files in the
* cm expire.
* @param enableOptimize whether to enable indexing
* @since 1.0
*/
public Cm(String areaName, ExpirationListener listener, boolean enableOptimize) {
try {
ResourceBundle cmRsrc = ResourceBundle.getBundle( "net.jxta.user" );
String str = cmRsrc.getString( "impl.cm.searchMethod" ).trim();
if (str.equals("RAW") ) {
searchMethod = RAW;
} else if (str.equals("CACHE") ) {
searchMethod = CACHE;
} else if (str.equals("INDEX") ) {
searchMethod = INDEX;
}
} catch ( MissingResourceException e) {
if (LOG.isEnabledFor(Priority.WARN)){
LOG.warn("cm search method preference resource not found", e);
}
}
if( !enableOptimize ) {
searchMethod = RAW;
if (LOG.isEnabledFor(Priority.INFO)){
LOG.info( "Forcing search method to : RAW" );
}
}
if (LOG.isEnabledFor(Priority.INFO)){
LOG.info("Initializaing with search method : " + searchType[searchMethod] );
}
expireListener = listener;
try {
File base = new File(RootDirBase);
File[] docDirs = new File[3];
FileExpirationService.ExpirationListener expiryNotice = null;
rootDir = new File(base, areaName);
rootDir = new File(rootDir.getCanonicalPath());
switch( searchMethod ) {
case INDEX :
case CACHE :
try {
expiryNotice = new FileExpirationService.ExpirationListener() {
public boolean expired(File f) {
boolean needsDelete = expireListener.expired( f );
if( !needsDelete )
return needsDelete;
if (LOG.isEnabledFor(Priority.DEBUG)) {
LOG.debug(" removing " + f + " from cache.");
}
CmCache cmc = (CmCache)
caches.get(new File(f.getParent()).getName());
if( null != cmc )
cmc.remove(f.getName());
return true;
}
};
} catch ( Exception failed ) {
if (LOG.isEnabledFor(Priority.WARN)) {
LOG.warn( "Initialize of CACHE failed, using RAW" );
}
searchMethod = RAW;
enableOptimize = false;
}
break;
case RAW :
default :
}
if( null == expiryNotice )
expiryNotice = new FileExpirationService.ExpirationListener() {
public boolean expired(File f) {
boolean needsDelete = expireListener.expired( f );
return needsDelete;
}
};
// Initialize directories
docDirs[0] = initDir(TmpDirName);
docDirs[1] = initDir(PrivateDirName);
docDirs[2] = initDir(PublicDirName);
expirer = new FileExpirationService(schedulerService,
rootDir,
expiryNotice );
} catch ( Exception e) {
if (LOG.isEnabledFor(Priority.WARN))
LOG.warn("Unable to create Cm", e);
if( e instanceof RuntimeException )
throw (RuntimeException) e;
else
throw new UndeclaredThrowableException( e );
}
}
/**
* Generates a random file name using doc hashcode
*
* @param doc to hash to generate a unique name
* @return String a random file name
* @since 1.0
*/
// XXX the cm is a CACHE it is not a STORE, advertisements will
// come and go, and there's no guarantee a doc will persist.
// the intention here is to avoid duplicate adv littering the cm,
// and prefrence is less docs, over unmanageable dups
// with the introduction of new adv. format this probability will cease to
// exist since all adv will be identified by an id hamada
public static String createTmpName(StructuredDocument doc) {
int hash = 0;
try {
StringWriter out = new StringWriter();
((StructuredTextDocument) doc).sendToWriter(out);
hash = out.toString().hashCode();
out.close();
} catch (IOException ex) {
}
return "cm" + Integer.toString(hash);
}
/**
* Returns the absolute time in milliseconds at which the file will expire.
*
* @param dn contains the name of the folder
* @param fn contains the name of the file
* @returns the absolute time in milliseconds at which this document will
* expire. -1 is returned if the file is not recognized or already expired.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -