alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.core.projects.cache;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import org.openide.ErrorManager;

import org.openide.filesystems.*;
import org.openide.util.Lookup;
import org.openide.util.SharedClassObject;
import org.openide.util.actions.SystemAction;
import org.openide.util.io.NbObjectInputStream;

/**
 * Read-only and fixed FileSystem over a binary file.
 * Its content can't be changed in any way, it can only be replaced by a new
 * instance over a different binary file.
 *
 * @author Petr Nejedly
 */
public class BinaryFS extends FileSystem {
/*
    private final static String[] KNOWN_STRINGS = {
	"SystemFileSystem.localizingBundle", // -1
	"SystemFileSystem.icon", // -2
	"instanceClass", // -3
	"instanceCreate", // -4
    };

    private final static String[] ATTR_TYPES = {
        "bytevalue",
        "shortvalue",
        "intvalue",
        "longvalue",
        "floatvalue",
        "doublevalue",
        "boolvalue",
        "charvalue",
        "stringvalue",
        "urlvalue",
        "methodvalue",
        "newvalue",
        "serialvalue",
    };
*/
    
    static final byte[] MAGIC = "org.netbeans.core.projects.cache.BinaryFS".getBytes(); // NOI18N
    
    /** An empty array of SystemActions. */
    static final SystemAction[] NO_ACTIONS = new SystemAction[0];

    /** An empty array of FileObjects. */
    static final FileObject[] NO_CHILDREN = new FileObject[0];

    String binaryFile;
//    RandomAccessFile file;
    byte [] content;
    
    private FileObject root;
    /** list of urls (String) or Date of their modifications */
    private java.util.List modifications;
    private Date lastModified = new Date();
    
    /** Creates a new instance of BinaryFS */
    public BinaryFS(String binaryFile) {
        this.binaryFile = binaryFile;
        try {
            RandomAccessFile file = new RandomAccessFile(binaryFile, "r"); // NOI18N
            byte[] magic = new byte[MAGIC.length];
            file.read(magic);
            for (int i = 0; i < MAGIC.length; i++) {
                if (magic[i] != MAGIC[i]) {
                    throw new IOException("Bad magic header: " + new String(magic)); // NOI18N
                }
            }

            // read root names
            content = new byte[4];
            file.readFully (content);
            Pointer sizePointer = new Pointer (0);
            int size = sizePointer.getInt ();
            
            content = new byte[size];
            file.readFully (content);

            modifications = new ArrayList ();
            Pointer p = new Pointer (0);
            while (p.offset < size) {
                String s = p.getString ();
                modifications.add (s);
            }
            
            content = new byte[(int)file.length() - MAGIC.length - 4 - size];
            file.readFully(content);
            file.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
        root = new BFSFolder("", null, 0);
        //setSystemName("Binary:"+binaryFile); // NOI18N
    }
    
    /** Finds a file given its full resource path.
     * @param name the resource path, e.g. "dir/subdir/file.ext" or "dir/subdir" or "dir"
     * @return a file object with the given path or
     *   null if no such file exists
     *
     */
    public FileObject findResource(String name) {
        if (name.length () == 0) {
            return root;
        }
        
        StringTokenizer st = new StringTokenizer(name, "/");
        FileObject fo = root;
        while (fo != null && st.hasMoreTokens()) {
            String next = st.nextToken();
            fo = fo.getFileObject(next, null); // XXX ??
        }

        return fo;
    }
    
    /** Returns an array of actions that can be invoked on any file in
     * this filesystem.
     * These actions should preferably
     * support the {@link org.openide.util.actions.Presenter.Menu Menu},
     * {@link org.openide.util.actions.Presenter.Popup Popup},
     * and {@link org.openide.util.actions.Presenter.Toolbar Toolbar} presenters.
     *
     * @return array of available actions
     *
     */
    public SystemAction[] getActions() {
        return NO_ACTIONS;
    }
    
    /** Provides a name for the system that can be presented to the user.
     * 

* This call should never be used to attempt to identify the file root * of the filesystem. On some systems it may happen to look the same but this is a * coincidence and may well change in the future. Either check whether * you are working with a {@link LocalFileSystem} or similar implementation and use * {@link LocalFileSystem#getRootDirectory}; or better, try * {@link FileUtil#toFile} which is designed to do this correctly. * * @return user presentable name of the filesystem * */ public String getDisplayName() { return "BinaryFS[" + binaryFile + "]"; } /** Getter for root folder in the filesystem. * * @return root folder of whole filesystem * */ public FileObject getRoot() { // System.err.println("returning root: " + root); return root; } /** Test if the filesystem is read-only or not. * @return true if the system is read-only * */ public boolean isReadOnly() { return true; } class Pointer { int offset; public Pointer(int start) { offset = start; } public int getOffset() { return offset; } public void shift(int len) { offset += len; } public String toString() { return "Ptr[" + offset + "]"; } public int getInt() throws IOException { int retVal = ((int)content[offset++]) & 0xff | (((int)content[offset++]) & 0xff) << 8 | (((int)content[offset++]) & 0xff) << 16 | (((int)content[offset++]) & 0xff) << 24; return retVal; } /** get the byte from the offset */ protected byte getByte() throws IOException { return content[offset++]; } /** get the String from the offset */ protected String getString() throws IOException { int len = getInt(); String s = new String(content, offset, len, "UTF-8"); //.intern(); // NOI18N offset += len; return s; } // File byte array accessor: private byte[] getBytes(int len) throws IOException { byte[] ret = new byte[len]; System.arraycopy(content, offset, ret, 0, len); offset += len; return ret; } } /* class Pointer { int offset; public Pointer(int start) { offset = start; } public int getOffset() { return offset; } public void shift(int len) { offset += len; } public String toString() { return "Ptr[" + offset + "]"; } public int getInt() throws IOException { byte[] arr = getBytes(4); int rv1 = ((int)arr[0]) & 0xff; int rv2 = (((int)arr[1]) & 0xff) << 8; int rv3 = (((int)arr[2]) & 0xff) << 16; int rv4 = (((int)arr[3]) & 0xff) << 24; int retVal = rv1 | rv2 | rv3 | rv4; return retVal; } /** get the byte from the offset * protected byte getByte() throws IOException { byte[] arr = getBytes(1); return arr[0]; } /** get the String from the offset * protected String getString() throws IOException { int len = getInt(); byte[] arr = getBytes(len); return new String(arr, "UTF-8").intern(); } // File byte array accessor: private byte[] getBytes(int len) throws IOException { byte[] ret = new byte[len]; synchronized (file) { file.seek(offset); file.readFully(ret); } offset += len; return ret; } } */ /** Base class for read-only FileObject, both file and folder * Handles common operations and throws exception for any modification * attempt. * Also handles attribute reading/parsing. * The layout in the bfs file is (beggining from the offset): *

     *   int attrCount
     *   Attribute[attrCount] attrs
     *   int fileCount/filesize
     *   content
     * 
*/ private abstract class BFSBase extends FileObject { // fields from the constructor private final FileObject parent; protected final String name; protected final int offset; // fetched fields private boolean initialized = false; private Map attrs = Collections.EMPTY_MAP; //MapAttribute> public BFSBase(String name, FileObject parent, int offset) { this.name = name; this.parent = parent; this.offset = offset; } public final boolean equals(Object o) { if (!(o instanceof BFSBase)) return false; if (o == this) return true; BFSBase f = (BFSBase)o; return f.getPath().equals(getPath()) && specificEquals(f); } public final int hashCode() { return getPath().hashCode(); } protected abstract boolean specificEquals(BFSBase f); /** no-op implementations of read-only, fixed, never firing FS */ public void addFileChangeListener(FileChangeListener fcl) {} public void removeFileChangeListener(FileChangeListener fcl) {} public boolean isReadOnly() { return true; } public void setImportant(boolean b) {} public FileObject createData(String name, String ext) throws IOException { throw new IOException(); // Read-only } public FileObject createFolder(String name) throws IOException { throw new IOException(); // Read-only } public void delete(FileLock lock) throws IOException { throw new IOException(); // Read-only } public OutputStream getOutputStream(FileLock lock) throws java.io.IOException { throw new IOException(); // Read-only } public FileLock lock() throws IOException { throw new IOException(); // Read-only } public void rename(FileLock lock, String name, String ext) throws IOException { throw new IOException(); // Read-only } public void setAttribute(String attrName, Object value) throws IOException { throw new IOException(); // Read-only } // simple common implementations: /** Get the filesystem containing this file. */ public FileSystem getFileSystem() throws FileStateInvalidException { return BinaryFS.this; } /** Get the parent folder. */ public FileObject getParent() { return parent; } /** Test whether this object is the root folder. */ public boolean isRoot() { return parent == null; } public boolean isValid() { return true; } /** Get last modification time. */ public java.util.Date lastModified() { return lastModified; } /** Get the name without extension of this file or folder. */ public String getName () { int i = name.lastIndexOf ('.'); return i <= 0 ? name : name.substring (0, i); } /** Get the extension of this file or folder. */ public String getExt () { int i = name.lastIndexOf ('.') + 1; return i <= 1 || i == name.length () ? "" : name.substring (i); // NOI18N } /** Getter for name and extension of a file object. */ public String getNameExt () { return name; } // Attributes implementation: /** Get the file attribute with the specified name. */ public Object getAttribute(String attrName) { initialize(); AttrImpl attr = (AttrImpl)attrs.get(attrName); if (attr != null) { FileObject topFO = null; // XXX big hack! See #29356 for explanation for this nonsense. try { Class mfoClass = Class.forName("org.openide.filesystems.MultiFileObject"); //NOI18N Field field = mfoClass.getDeclaredField("attrAskedFileObject"); //NOI18N field.setAccessible(true); ThreadLocal attrAskedFileObject = (ThreadLocal) field.get(null); topFO = (FileObject) attrAskedFileObject.get(); attrAskedFileObject.set(null); } catch (Exception e) { ErrorManager.getDefault().notify(e); } return attr.getValue(topFO == null ? this : topFO, attrName); } else { return null; } } /** Get all file attribute names for this file. */ public Enumeration getAttributes() { initialize(); if (attrs == null) return org.openide.util.Enumerations.empty(); return Collections.enumeration(attrs.keySet()); } /** * A method for fetching/parsing the content of the file/folder * to the memory. Should be called before any access operation * to check the content of the entity. */ protected final void initialize() { if (initialized) return; try { Pointer ptr = new Pointer(offset); int attrCount = ptr.getInt(); if (attrCount > 0) attrs = new HashMap(attrCount*4/3+1); for (int i=0; i< attrCount; i++) { // do read attribute String name = ptr.getString(); // String attrName byte type = ptr.getByte(); // byte attrType String value = ptr.getString(); // String attrValue attrs.put(name, new AttrImpl(type, value)); } doInitialize(ptr); } catch (Exception e) { System.err.println("exception in initialize() on " + name + ": " + e); } initialized = true; } /** A method called to finish the initialization in the subclasses. * When this method is called, the contentOffset field is already set up. */ protected abstract void doInitialize(Pointer ptr) throws Exception; } static final class AttrImpl { private int index; private String value; AttrImpl(int type, String textValue) { index = type; value = textValue; } public Object getValue( FileObject fo, String attrName) { try { switch(index) { case 0: // bytevalue return Byte.valueOf(value); case 1: // shortvalue return Short.valueOf(value); case 2: // intvalue return Integer.valueOf(value); case 3: // longvalue return Long.valueOf(value); case 4: // floatvalue return Float.valueOf(value); case 5: // doublevalue return Double.valueOf(value); case 6: // boolvalue return Boolean.valueOf(value); case 7: // charvalue if (value.trim().length() != 1) break; return new Character(value.charAt(0)); case 8: // stringvalue return value; case 9: // urlvalue return new URL(value); case 10: // methodvalue return methodValue (value,fo,attrName); case 11: // newvalue Class cls = findClass (value); // special support for singletons if (SharedClassObject.class.isAssignableFrom(cls)) { return SharedClassObject.findObject(cls, true); } else { return cls.newInstance(); } case 12: // serialvalue return decodeValue(value); default: throw new IllegalStateException("Bad index: " + index); // NOI18N } } catch (Exception exc) { ErrorManager em = ErrorManager.getDefault(); em.annotate (exc, "value = "+value); //NOI18N em.notify (ErrorManager.INFORMATIONAL, exc); } return null; // problem getting the value... } /** Constructs new attribute as Object. Used for dynamic creation: methodvalue. */ private Object methodValue(String method, FileObject fo, String attr) throws Exception { String className,methodName; int i = method.lastIndexOf('.'); if (i != -1) { methodName = value.substring(i+1); className = value.substring(0,i); Class cls = findClass (className); Object objArray[][] = {null,null,null}; Method methArray[] = {null,null,null}; Class fParam = fo.getClass(), sParam = attr.getClass(); Method[] allMethods = cls.getDeclaredMethods(); Class[] paramClss; for (int j=0; j < allMethods.length; j++) { if (!allMethods[j].getName().equals(methodName)) continue; paramClss = allMethods[j].getParameterTypes(); if (paramClss.length == 0) { if (methArray[0] == null) { methArray[0] = allMethods[j]; objArray[0] = new Object[] {}; continue; } continue; } if (paramClss.length == 2 && methArray[2] == null) { if (paramClss[0].isAssignableFrom(fParam) && paramClss[1].isAssignableFrom(sParam)) { methArray[2] = allMethods[j]; objArray[2] = new Object[] {fo,attr}; break; } if (paramClss[0].isAssignableFrom(sParam) && paramClss[1].isAssignableFrom(fParam)) { methArray[2] = allMethods[j]; objArray[2] = new Object[] {attr,fo}; break; } continue; } if (paramClss.length == 1 && methArray[1] == null) { if (paramClss[0].isAssignableFrom(fParam)) { methArray[1] = allMethods[j]; objArray[1] = new Object[] {fo}; continue; } if (paramClss[0].isAssignableFrom(sParam)) { methArray[1] = allMethods[j]; objArray[1] = new Object[] {attr}; continue; } continue; } } for (int k = 2; k >= 0; k-- ) {//clsArray.length if (methArray[k] != null) { //Method meth = cls.getDeclaredMethod(methodName,clsArray[k]); methArray[k].setAccessible(true); //otherwise cannot invoke private return methArray[k].invoke(null,objArray[k]); } } } // Some message to logFile throw new InstantiationException (value); } private Object decodeValue(String value) throws Exception { if ((value == null) ||(value.length() == 0)) return null; byte[] bytes = new byte[value.length()/2]; int count = 0; for (int i = 0; i < value.length(); i += 2) { // way from effective!!!!! int tempI = Integer.parseInt(value.substring(i,i+2),16); if (tempI > 127) tempI -=256; // ?? necessary ?? bytes[count++] = (byte) tempI; } ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 0, count); return new NbObjectInputStream(bis).readObject(); } /** Loads a class of given name * @param name name of the class * @return the class * @exception ClassNotFoundException if class was not found */ private Class findClass (String name) throws ClassNotFoundException { ClassLoader c = (ClassLoader)Lookup.getDefault ().lookup (ClassLoader.class); String tname = org.openide.util.Utilities.translate (name); if (c == null) { return Class.forName (tname); } else { return Class.forName (tname, true, c); } } } /** FileContent: int attrCount Attribute[attrCount] attrs int contentLength (or -1 for uri) byte[contentLength] content (or String uri) */ final class BFSFile extends BFSBase { private int len; private int contentOffset; private String uri; private long lastModified = -1; public BFSFile(String name, FileObject parent, int offset) { super(name, parent, offset); } /** Get all children of this folder (files and subfolders). */ public FileObject[] getChildren() { return NO_CHILDREN; } /** Retrieve file or folder contained in this folder by name. */ public FileObject getFileObject(String name, String ext) { return null; // File have no children } /** Test whether this object is a data object. */ public boolean isData() { return true; } /** Test whether this object is a folder. */ public boolean isFolder() { return false; } private byte[] data() throws IOException { if (len == -1) throw new IllegalArgumentException(); return new Pointer(contentOffset).getBytes(len); } /** Get input stream. */ public InputStream getInputStream() throws java.io.FileNotFoundException { initialize(); try { return len == -1 ? // URI or not new URL(uri).openConnection().getInputStream() : // len from URI new ByteArrayInputStream(data()); } catch (Exception e) { FileNotFoundException x = new FileNotFoundException (e.getMessage()); ErrorManager.getDefault().annotate(x,e); throw x; } } /** Get the size of the file. */ public long getSize() { initialize(); try { return len == -1 ? // URI or not new URL(uri).openConnection().getContentLength() : // len from URI len; // len from dump } catch (Exception e) { System.err.println("exception in getSize() on " + name + ": " + e); return 0; } } /** A method called to finish the initialization in the subclasses. * When this method is called, the contentOffset field is already set up. * * the rest of the FileContent: * int contentLength (or -1) * byte[contentLength] content (or String uri); */ protected void doInitialize(Pointer ptr) throws Exception { len = ptr.getInt();; contentOffset = ptr.getOffset(); if (len == -1) { uri = ptr.getString(); } else { ptr.shift (len); } int base = ptr.getInt (); lastModified = -10 - base; } // equals compares data: URI or byte contents. protected boolean specificEquals(BFSBase _f) { if (!(_f instanceof BFSFile)) return false; BFSFile f = (BFSFile)_f; initialize(); f.initialize(); if (len == -1 && f.len == -1) { return uri.equals(f.uri); } else if (len != -1 && f.len != -1) { byte[] data, fdata; try { data = data(); fdata = f.data(); } catch (IOException ioe) { return false; } if (data.length != fdata.length) return false; for (int i = 0; i < data.length; i++) { if (data[i] != fdata[i]) return false; } return true; } else { return false; } } public java.util.Date lastModified () { initialize(); if (lastModified >= 0) { return new java.util.Date (lastModified); } try { int index = -1; java.net.URLConnection conn = null; if (len == -1) { conn = new URL(uri).openConnection (); } else { synchronized (modifications) { index = ((int)-lastModified) - 10; Object obj = modifications.get (index); if (obj instanceof Date) { return (Date)obj; } conn = new URL ((String)obj).openConnection (); } } if (conn instanceof java.net.JarURLConnection) { conn = ((java.net.JarURLConnection)conn).getJarFileURL ().openConnection (); } if (conn != null) { long date = conn.getLastModified (); if (date > 0) { lastModified = date; Date d = new java.util.Date (date); if (index >= 0) { synchronized (modifications) { modifications.set (index, d); } } return d; } } } catch (Exception e) { ErrorManager.getDefault().notify (ErrorManager.INFORMATIONAL, e); } return super.lastModified (); } } private class BFSFolder extends BFSBase { Map childrenMap = Collections.EMPTY_MAP; public BFSFolder(String name, FileObject parent, int offset) { super(name, parent, offset); } /** Test whether this object is a data object. */ public boolean isData() { return false; } /** Test whether this object is a folder. */ public boolean isFolder() { return true; } /** Get the size of the file. */ public long getSize() { return 0; // Folder is zero } /** Get input stream. */ public InputStream getInputStream() throws java.io.FileNotFoundException { throw new FileNotFoundException("Is a directory: " + this); } /** Get all children of this folder (files and subfolders). */ public FileObject[] getChildren() { initialize(); return (FileObject[])childrenMap.values().toArray(NO_CHILDREN); } /** Retrieve file or folder contained in this folder by name. */ public FileObject getFileObject(String name, String ext) { initialize(); String fullName = ext == null ? name : name + "." + ext; // XXX - ?? return (FileObject)childrenMap.get(fullName); } /** A method called to finish the initialization in the subclasses. * When this method is called, the contentOffset field is already set up. * * the rest of the FolderContent: * int fileCount * File[fileCount] references * File/FolderContent[fileCount] contents */ protected void doInitialize(Pointer ptr) throws Exception { int files = ptr.getInt(); if (files > 0) { childrenMap = new HashMap(files*4/3+1); for (int i=0; i
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.