001    package toolbus.viewer;
002    
003    import java.io.File;
004    import java.io.FileInputStream;
005    import java.io.IOException;
006    import java.nio.ByteBuffer;
007    import java.nio.channels.FileChannel;
008    import toolbus.ToolBus;
009    import toolbus.util.collections.ConcurrentHashMap;
010    
011    /**
012     * This store provides access to all, for the ToolBus, reachable source code. Additionally it
013     * caches the already loaded code.
014     * 
015     * @author Arnold Lankamp
016     */
017    public class ScriptCodeStore{
018            private final ToolBus toolbus;
019            private final ConcurrentHashMap<String, byte[]> scriptCodeCache;
020            
021            /**
022             * Constructor.
023             * 
024             * @param toolbus
025             *            The ToolBus with which this store will be associated.
026             */
027            public ScriptCodeStore(ToolBus toolbus){
028                    super();
029                    
030                    this.toolbus = toolbus;
031                    
032                    scriptCodeCache = new ConcurrentHashMap<String, byte[]>();
033            }
034            
035            /**
036             * Returns the list of absolute paths to all, for the ToolBus, reachable scripts. Returns null
037             * in case the scripts haven't been parsed yet.
038             * 
039             * @return The list of absolute paths to all, for the ToolBus, reachable scripts; null in case
040             * the scripts haven't been parsed yet.
041             */
042            public String[] getScriptNames(){
043                    return toolbus.getIncludedScripts();
044            }
045            
046            /**
047             * Retrieves the source code of the script indicated by the given path.
048             * 
049             * @param scriptPath
050             *            The path to the script we want to load.
051             * @return The retrieved source code of the script.
052             * @throws IOException Thrown when something I/O related goes wrong (obviously).
053             */
054            public byte[] getCode(String scriptPath) throws IOException{
055                    byte[] scriptCode = scriptCodeCache.get(scriptPath);
056                    if(scriptCode != null) return scriptCode;
057                    
058                    File scriptFile = new File(scriptPath);
059                    if(!scriptFile.exists() || !scriptFile.isFile()) throw new IOException("No such script file: "+scriptPath);
060                    
061                    int fileSize = (int) scriptFile.length();
062                    scriptCode = new byte[fileSize];
063                    
064                    FileInputStream fis = new FileInputStream(scriptFile);
065                    FileChannel fc = fis.getChannel();
066                    
067                    ByteBuffer byteBuffer = ByteBuffer.wrap(scriptCode);
068                    try{
069                            fc.read(byteBuffer);
070                    }finally{
071                            try{
072                                    fc.close();
073                            }finally{
074                                    fis.close();
075                            }
076                    }
077                    
078                    scriptCodeCache.put(scriptPath, scriptCode); // Put the retrieved code in the cache.
079                    
080                    return scriptCode;
081            }
082    }