📄 repository.java
字号:
}
if( pcl == null ) {
// allow delegation to embedding app
groupClassLoader=new RepositoryClassLoader(new URL[0], this);
} else {
groupClassLoader=new RepositoryClassLoader(new URL[0], pcl, this);
}
if( DEBUG ) log("---------- Created repository loader " + pcl );
}
return groupClassLoader;
}
/**
* Find a class in the group. It'll iterate over each loader
* and try to find the class - using only the method that
* search locally or on parent ( i.e. not in group, to avoid
* recursivity ).
*
*
* @param classN
* @return
*/
Class findClass(ClassLoader caller, String classN ) {
Class clazz=null;
// do we have it in index ?
if( USE_IDX ) {
int lastIdx=classN.lastIndexOf(".");
String prefix=(lastIdx>0) ? classN.substring(0, lastIdx) : classN;
Object mO=prefixes.get(prefix.replace('.', '/'));
if( mO!=null ) {
if( mO instanceof Module ) {
Module m=(Module)mO;
try {
Class c=((ModuleClassLoader)m.getClassLoader()).findLocalClass(classN);
//log("Prefix: " +prefix + " " + classN + " " + m);
return c;
} catch (Exception e) {
//log("Prefix err: " +prefix + " " + classN + " " + m + " " + e);
//return null;
}
} else {
Module mA[]=(Module[])mO;
for( int i=0; i<mA.length; i++ ) {
Module m=mA[i];
try {
Class c=((ModuleClassLoader)m.getClassLoader()).findLocalClass(classN);
//log("Prefix: " +prefix + " " + classN + " " + m);
return c;
} catch (Exception e) {
//log("Prefix err: " +prefix + " " + classN + " " + m + " " + e);
//return null;
}
}
}
}
}
// TODO: move the vector to a []
for( int i=loaders.size()-1; i>=0; i-- ) {
// TODO: for regular CL, just use loadClass, they'll not recurse
// The behavior for non-SCL or not in the group loader is the same as for parent loader
ModuleClassLoader cl=(ModuleClassLoader)loaders.elementAt(i);
// TODO: move loaders with index in separate vector
//if( cl.getModule().hasIndex ) continue;
if( cl== caller ) continue;
//if( classN.indexOf("SmtpCoyoteProtocolHandler") > 0 ) {
//log("try " + cl.debugObj + " " + name + " " + classN + " " + loaders.size());
//}
try {
if( cl instanceof ModuleClassLoader ) {
clazz=((ModuleClassLoader)cl).findLocalClass(classN );
} else {
clazz=cl.findClass(classN);
}
//System.err.println("GRPLD: " + classN + " from " + info.get(cl));
return clazz;
} catch (ClassNotFoundException e) {
//System.err.println("CNF: " + classN + " " + info.get(cl) );
//if( classN.indexOf("smtp") > 0 ) e.printStackTrace();
}
}
return null;
}
/**
* @param loader
* @param name2
* @return
*/
URL findResource(ModuleClassLoader caller, String classN) {
URL url=null;
if( DEBUG ) log("Repository.findResource " + classN + " " + caller );
for( int i=loaders.size()-1; i>=0; i-- ) {
// TODO: for regular CL, just use loadClass, they'll not recurse
// The behavior for non-SCL or not in the group loader is the same as for parent loader
ModuleClassLoader cl=(ModuleClassLoader)loaders.elementAt(i);
if( cl== caller ) continue;
url=((ModuleClassLoader)cl).findResource(classN );
if( url!=null )
return url;
}
return null;
}
private void log(String s) {
System.err.println("Repository (" + name + "): " + s );
}
/**
* @param name2
*/
public void setName(String name2) {
this.name=name2;
}
/*
* Work in progress:
*
* -use the INDEX.LIST to get prefixes to avoid linear
* search in repositories.
*
* - serialize the state ( including timestamps ) to improve startup time
* ( avoids the need to open all jars - if INDEX.LIST is ok)
*/
/**
* Read the index. The index contain packages and top level resources
*
* @param cl
* @throws Exception
*/
private void processJarIndex(Module m) throws Exception {
ModuleClassLoader cl=(ModuleClassLoader)m.createClassLoader();
// only support index for modules with a single jar in CP
String cp=m.getClasspathString();
if( ! cp.endsWith(".jar")) return;
URL urlIdx=cl.findResource("META-INF/INDEX.LIST");
if( urlIdx == null ) {
log("INDEX.LIST not found, run: jar -i " + m.getClasspathString());
return;
}
try {
InputStream is=urlIdx.openStream();
if( is==null ) {
log("Can't read " + urlIdx + " " + m.getClasspathString());
return;
}
BufferedReader br=new BufferedReader( new InputStreamReader(is) );
String line=br.readLine();
if( line==null ) return;
if( ! line.startsWith( "JarIndex-Version:") ||
! line.endsWith("1.0")) {
log("Invalid signature " + line + " " + m.getClasspathString());
}
br.readLine(); // ""
while( readSection(br, m) ) {
}
m.hasIndex=true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private boolean readSection( BufferedReader br, Module m) throws IOException {
String jarName=br.readLine();
if( jarName==null ) return false; // done
if( "".equals( jarName )) {
log("Invalid jarName " + jarName + " " + m.getClasspathString() );
return false;
}
//log("Index " + jarName + " " + m.getClasspathString());
String prefix=null;
while( ((prefix=br.readLine()) != null ) &&
(! "".equals( prefix )) ) {
//log("found " + prefix + " " + m);
Object o=prefixes.get(prefix);
if( o == null ) {
prefixes.put(prefix, m);
} else {
Module mA[]=null;
if( o instanceof Module ) {
mA=new Module[2];
mA[0]=(Module)o;
mA[1]=m;
} else {
Object oldA[]=(Module[])o;
mA=new Module[oldA.length + 1];
System.arraycopy(oldA, 0, mA, 0, oldA.length);
mA[oldA.length]=m;
}
prefixes.put( prefix, mA);
//log("Multiple prefixes: " + prefix + " " + mA);
}
}
return prefix!=null;
}
/** Read loader.REPO.cache from work dir
*
* This file will hold timestamps for each module/jar and cache the INDEX -
* to avoid opening the jars/modules that are not used
*
* @throws IOException
*/
private void readCachedIdx() throws IOException {
}
/** Check the index and verify that:
* - all jars are older than timestamp and still exist
* - there are no new jars
*
* @throws IOException
*/
private void checkCacheIdx() throws IOException {
}
private void writeCacheIdx() throws IOException {
// For each module we write the timestamp, filename then the index
// The idea is to load this single file to avoid scanning many jars
// we'll use the cache
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -