StreamEntryIterator.java :  » REST » alc-rest » org » allcolor » alc » filesystem » priv » Java Open Source

Java Open Source » REST » alc rest 
alc rest » org » allcolor » alc » filesystem » priv » StreamEntryIterator.java
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
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.