package org.allcolor.alc.filesystem.priv;
import org.allcolor.alc.filesystem.FileSystem;
import org.allcolor.alc.filesystem.priv.FSUtils.DirectoryElement;
import org.allcolor.alc.filesystem.priv.FSUtils.FileElement;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @author (Author)
* @version $Revision$
*/
interface StreamEntryIterator
extends Serializable {
//~ Methods ------------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
*/
public StreamEntry getNextEntry ()
throws IOException;
//~ Inner Interfaces ---------------------------------------------------------
/**
* @author (Author)
* @version $Revision$
*/
public static interface FileCallBack {
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param in DOCUMENT ME!
*/
public void file (final java.io.File in);
} // end FileCallBack
//~ Inner Classes ------------------------------------------------------------
/**
* @author (Author)
* @version $Revision$
*/
public static class C
implements Serializable {
//~ Static fields/initializers ---------------------------------------------
/**
* DOCUMENT ME!
*/
private static volatile long last = System.currentTimeMillis ();
/**
* DOCUMENT ME!
*/
private static final ThreadLocal<byte[]> localbuffer = new ThreadLocal<byte[]>();
/**
* DOCUMENT ME!
*/
private static final Map<String, Reference<byte[]>> map = new HashMap<String, Reference<byte[]>>();
/**
* DOCUMENT ME!
*/
private static final Map<String, Reference<Method>> mapClassMethod = new WeakHashMap<String, Reference<Method>>();
/**
* DOCUMENT ME!
*/
private static final Map<String, Reference<Method>> mapStreamClassMethod = new WeakHashMap<String, Reference<Method>>();
/**
* DOCUMENT ME!
*/
private static final Class<?> proxyClass = Proxy.getProxyClass (
StreamEntry.class.getClassLoader (),
new Class [] { StreamEntry.class });
/**
* DOCUMENT ME!
*/
private static final Constructor<?> proxyClassConstructor = C
.getproxyClassConstructor ();
/**
* DOCUMENT ME!
*/
private static final Class<?> proxyIteratorClass = Proxy.getProxyClass (
StreamEntry.class.getClassLoader (),
new Class [] { StreamEntryIterator.class });
/**
* DOCUMENT ME!
*/
private static final Constructor<?> proxyIteratorClassConstructor = C
.getproxyIteratorClassConstructor ();
/**
* DOCUMENT ME!
*/
public static final long serialVersionUID = 1L;
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param in DOCUMENT ME!
* @param path DOCUMENT ME!
* @param fs DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
*/
public static final InputStream findEntryAsStream (
final InputStream in,
final String path,
final FileSystem fs)
throws IOException {
C.removeFreed ();
synchronized (C.map) {
final Reference<byte[]> ref = C.map.get (fs.getLabel () + ":" + path);
if (ref != null) {
final byte tmp[] = ref.get ();
if (tmp != null) {
return new ByteArrayInputStream(tmp);
} // end if
} // end if
} // end synchronized
try {
final StreamEntryIterator zin = C.createStreamFromStream (in);
StreamEntry entry = null;
while ((entry = zin.getNextEntry ()) != null) {
if (! entry.isDirectory ()) {
final boolean isWantedEntry = ("/" + entry.getName ()).equals (
path);
final String fsEntryName = fs.getLabel () + ":/" + entry.getName ();
Reference<byte[]> refRead = null;
synchronized (C.map) {
refRead = C.map.get (fsEntryName);
} // end synchronized
if ((refRead != null) && isWantedEntry) {
final byte file[] = refRead.get ();
if (file != null) {
return new ByteArrayInputStream(file);
} // end if
refRead = null;
} // end if
if ((refRead != null) && (refRead.get () != null)) {
continue;
} // end if
if (isWantedEntry) {
final byte file[] = C.readAll (new BufferedInputStream(in));
synchronized (C.map) {
C.map.put (
fsEntryName,
new SoftReference<byte[]>(file));
} // end synchronized
return new ByteArrayInputStream(file);
} // end if
} // end if
} // end while
} // end try
finally {
in.close ();
} // end finally
throw new IOException("File not found.");
} // end findEntryAsStream()
/**
* DOCUMENT ME!
*
* @param in DOCUMENT ME!
* @param fs DOCUMENT ME!
* @param callBack DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
*/
public static final void initReading (
final InputStream in,
final FileSystem fs,
final FileCallBack callBack)
throws IOException {
final StreamEntryIterator zin = C.createStreamFromStream (in);
StreamEntry entry = null;
while ((entry = zin.getNextEntry ()) != null) {
if (entry.isDirectory ()) {
final DirectoryElement dir = ( DirectoryElement ) fs.directory (
entry.getName ());
dir.setLastModifiedOn (entry.getTime ());
} // end if
else {
final FileElement filee = ( FileElement ) fs.file (entry.getName ());
filee.setLastModifiedOn (entry.getTime ());
} // end else
} // end while
in.close ();
} // end initReading()
/**
* DOCUMENT ME!
*
* @param in DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
*/
public static final byte [] readAll (final InputStream in)
throws IOException {
final ByteArrayOutputStream fout = new ByteArrayOutputStream();
byte buffer[] = C.localbuffer.get ();
if (buffer == null) {
buffer = new byte[4096];
C.localbuffer.set (buffer);
} // end if
int inb = -1;
while ((inb = in.read (buffer)) != -1) {
fout.write (buffer, 0, inb);
} // end while
return fout.toByteArray ();
} // end readAll()
/**
* DOCUMENT ME!
*
* @param entry DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private static StreamEntry createStreamEntryFromObject (final Object entry) {
if (entry == null) {
return null;
} // end if
final InvocationHandler handler = new InvocationHandler() {
public static final long serialVersionUID = 1L;
public Object invoke (
final Object proxy,
final Method method,
final Object args[])
throws Throwable {
try {
Reference<Method> refm = null;
synchronized (C.mapClassMethod) {
refm = C.mapClassMethod.get (
entry.getClass ().getName () + method.getName ());
} // end synchronized
Method toCall = (refm != null)
? refm.get ()
: null;
if (toCall == null) {
toCall = entry.getClass ()
.getMethod (
method.getName (),
method.getParameterTypes ());
synchronized (C.mapClassMethod) {
C.mapClassMethod.put (
entry.getClass ().getName () + method.getName (),
new WeakReference<Method>(toCall));
} // end synchronized
} // end if
Object obj = toCall.invoke (entry, args);
if (obj instanceof Date) {
return new Long((( Date ) obj).getTime ());
} // end if
return obj;
} // end try
catch (final Exception e) {
if ("getTime".equals (method.getName ())) {
Method toCall = entry.getClass ()
.getMethod (
"getModTime",
method.getParameterTypes ());
synchronized (C.mapClassMethod) {
C.mapClassMethod.put (
entry.getClass ().getName () + method.getName (),
new WeakReference<Method>(toCall));
} // end synchronized
Date date = ( Date ) toCall.invoke (entry, args);
if (date != null) {
return new Long(date.getTime ());
} // end if
} // end if
} // end catch
return null;
} // end invoke()
} // end new
;
try {
return ( StreamEntry ) C.proxyClassConstructor.newInstance (
new Object [] { handler });
} // end try
catch (final Exception e) {
return null;
} // end catch
} // end createStreamEntryFromObject()
/**
* DOCUMENT ME!
*
* @param stream DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private static StreamEntryIterator createStreamFromStream (
final Object stream) {
final InvocationHandler handler = new InvocationHandler() {
public static final long serialVersionUID = 1L;
public Object invoke (
final Object proxy,
final Method method,
final Object args[])
throws Throwable {
Reference<Method> refm = null;
synchronized (C.mapStreamClassMethod) {
refm = C.mapStreamClassMethod.get (
stream.getClass ().getName () + method.getName ());
} // end synchronized
Method toCall = (refm != null)
? refm.get ()
: null;
if (toCall == null) {
toCall = stream.getClass ()
.getMethod (
method.getName (),
method.getParameterTypes ());
synchronized (C.mapStreamClassMethod) {
C.mapStreamClassMethod.put (
stream.getClass ().getName () + method.getName (),
new WeakReference<Method>(toCall));
} // end synchronized
} // end if
return C.createStreamEntryFromObject (toCall.invoke (stream, args));
} // end invoke()
} // end new
;
try {
return ( StreamEntryIterator ) C.proxyIteratorClassConstructor
.newInstance (new Object [] { handler });
} // end try
catch (final Exception e) {
return null;
} // end catch
} // end createStreamFromStream()
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private static final Constructor<?> getproxyClassConstructor () {
try {
return C.proxyClass.getConstructor (
new Class [] { InvocationHandler.class });
} // end try
catch (final Exception ignore) {
return null;
} // end catch
} // end getproxyClassConstructor()
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private static final Constructor<?> getproxyIteratorClassConstructor () {
try {
return C.proxyIteratorClass.getConstructor (
new Class [] { InvocationHandler.class });
} // end try
catch (final Exception ignore) {
return null;
} // end catch
} // end getproxyIteratorClassConstructor()
/**
* DOCUMENT ME!
*/
private static final void removeFreed () {
final long now = System.currentTimeMillis ();
if ((now - C.last) > 20000) {
C.last = now;
synchronized (C.map) {
try {
for (
final Iterator<Map.Entry<String, Reference<byte[]>>> it = C.map.entrySet ()
.iterator ();
it.hasNext ();) {
final Map.Entry<String, Reference<byte[]>> entry = it.next ();
final Reference<byte[]> file = entry.getValue ();
if (file.get () == null) {
it.remove ();
} // end if
} // end for
} // end try
catch (final Exception ignore) {}
} // end synchronized
} // end if
} // end removeFreed()
} // end C
} // end StreamEntryIterator
|