changed to unmaintained
[aaf/authz.git] / auth / auth-core / src / main / java / org / onap / aaf / auth / rserv / CachingFileAccess.java
index 53511b4..cdda50d 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,15 +24,12 @@ package org.onap.aaf.auth.rserv;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -52,45 +49,43 @@ import java.util.regex.Pattern;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.onap.aaf.misc.env.Env;
 import org.onap.aaf.misc.env.EnvJAXB;
 import org.onap.aaf.misc.env.LogTarget;
 import org.onap.aaf.misc.env.Store;
-import org.onap.aaf.misc.env.TimeTaken;
 import org.onap.aaf.misc.env.Trans;
 /*
  * CachingFileAccess
- * 
+ *
  * Author: Jonathan Gathman, Gathsys 2010
- *  
+ *
  */
 public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void> {
     public static void setEnv(Store store, String[] args) {
-        for(int i=0;i<args.length-1;i+=2) { // cover two parms required for each 
-            if(CFA_WEB_PATH.equals(args[i])) {
-                store.put(store.staticSlot(CFA_WEB_PATH), args[i+1]); 
-            } else if(CFA_CACHE_CHECK_INTERVAL.equals(args[i])) {
+        for (int i=0;i<args.length-1;i+=2) { // cover two parms required for each
+            if (CFA_WEB_PATH.equals(args[i])) {
+                store.put(store.staticSlot(CFA_WEB_PATH), args[i+1]);
+            } else if (CFA_CACHE_CHECK_INTERVAL.equals(args[i])) {
                 store.put(store.staticSlot(CFA_CACHE_CHECK_INTERVAL), Long.parseLong(args[i+1]));
-            } else if(CFA_MAX_SIZE.equals(args[i])) {
+            } else if (CFA_MAX_SIZE.equals(args[i])) {
                 store.put(store.staticSlot(CFA_MAX_SIZE), Integer.parseInt(args[i+1]));
             }
         }
     }
-    
-    private static String MAX_AGE = "max-age=3600"; // 1 hour Caching
+
+    private static String maxAge = "max-age=3600"; // 1 hour Caching
     private final Map<String,String> typeMap;
     private final NavigableMap<String,Content> content;
     private final Set<String> attachOnly;
-    public final static String CFA_WEB_PATH = "aaf_cfa_web_path";
+    public static final  String CFA_WEB_PATH = "aaf_cfa_web_path";
     // when to re-validate from file
     // Re validating means comparing the Timestamp on the disk, and seeing it has changed.  Cache is not marked
-    // dirty unless file has changed, but it still makes File IO, which for some kinds of cached data, i.e. 
+    // dirty unless file has changed, but it still makes File IO, which for some kinds of cached data, i.e.
     // deployed GUI elements is unnecessary, and wastes time.
     // This parameter exists to cover the cases where data can be more volatile, so the user can choose how often the
     // File IO will be accessed, based on probability of change.  "0", of course, means, check every time.
-    private final static String CFA_CACHE_CHECK_INTERVAL = "aaf_cfa_cache_check_interval";
-    private final static String CFA_MAX_SIZE = "aaf_cfa_max_size"; // Cache size limit
-    private final static String CFA_CLEAR_COMMAND = "aaf_cfa_clear_command";
+    private static final String CFA_CACHE_CHECK_INTERVAL = "aaf_cfa_cache_check_interval";
+    private static final String CFA_MAX_SIZE = "aaf_cfa_max_size"; // Cache size limit
+    private static final String CFA_CLEAR_COMMAND = "aaf_cfa_clear_command";
 
     // Note: can be null without a problem, but included
     // to tie in with existing Logging.
@@ -98,13 +93,15 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
     public long checkInterval; // = 600000L; // only check if not hit in 10 mins by default
     public int maxItemSize; // = 512000; // max file 500k
     private Timer timer;
-    private String web_path;
+    private String webPath;
     // A command key is set in the Properties, preferably changed on deployment.
     // it is compared at the beginning of the path, and if so, it is assumed to issue certain commands
-    // It's purpose is to protect, to some degree the command, even though it is HTTP, allowing 
+    // It's purpose is to protect, to some degree the command, even though it is HTTP, allowing
     // local batch files to, for instance, clear caches on resetting of files.
-    private String clear_command;
-    
+    private String clearCommand;
+
+    public static final String TEXT_PLAIN = "text/plain";
+
     public CachingFileAccess(EnvJAXB env, String ... args) throws IOException {
         super(null,"Caching File Access");
         setEnv(env,args);
@@ -117,7 +114,7 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
         typeMap.put("html","text/html");
         typeMap.put("css","text/css");
         typeMap.put("js","text/javascript");
-        typeMap.put("txt","text/plain");
+        typeMap.put("txt", TEXT_PLAIN);
         typeMap.put("xml","text/xml");
         typeMap.put("xsd","text/xml");
         attachOnly.add("xsd");
@@ -133,36 +130,48 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
         typeMap.put("jar","application/x-java-applet");
         typeMap.put("jnlp", "application/x-java-jnlp-file");
         typeMap.put("class", "application/java");
-        typeMap.put("props", "text/plain");
+        typeMap.put("props", TEXT_PLAIN);
         typeMap.put("jks", "application/octet-stream");
-        
+
+        // Fonts
+        typeMap.put("ttf","font/ttf");
+        typeMap.put("woff","font/woff");
+        typeMap.put("woff2","font/woff2");
+
+
         timer = new Timer("Caching Cleanup",true);
         timer.schedule(new Cleanup(content,500),60000,60000);
-        
+
         // Property params
-        web_path = env.get(env.staticSlot(CFA_WEB_PATH));
-        env.init().log("CachingFileAccess path: " + new File(web_path).getCanonicalPath());
+        webPath = env.get(env.staticSlot(CFA_WEB_PATH));
+        env.init().log("CachingFileAccess path: " + new File(webPath).getCanonicalPath());
         Object obj;
         obj = env.get(env.staticSlot(CFA_CACHE_CHECK_INTERVAL),600000L);  // Default is 10 mins
-        if(obj instanceof Long) {checkInterval=(Long)obj;
-        } else {checkInterval=Long.parseLong((String)obj);}
-        
+        if (obj instanceof Long) {
+          checkInterval=(Long)obj;
+        } else {
+          checkInterval=Long.parseLong((String)obj);
+        }
+
         obj = env.get(env.staticSlot(CFA_MAX_SIZE), 512000);    // Default is max file 500k
-        if(obj instanceof Integer) {maxItemSize=(Integer)obj;
-        } else {maxItemSize =Integer.parseInt((String)obj);}
-              
-         clear_command = env.getProperty(CFA_CLEAR_COMMAND,null);
+        if (obj instanceof Integer) {
+          maxItemSize=(Integer)obj;
+        } else {
+          maxItemSize =Integer.parseInt((String)obj);
+        }
+
+         clearCommand = env.getProperty(CFA_CLEAR_COMMAND,null);
     }
 
-    
+
 
     @Override
     public void handle(TRANS trans, HttpServletRequest req, HttpServletResponse resp) throws IOException {
         String key = pathParam(req, ":key");
-        String cmd = pathParam(req,":cmd");
-        if(key.equals(clear_command)) {
+        int slash = key.indexOf('/');
+        if(key.length()>2 && slash>=0 && key.substring(0,slash).equals(clearCommand)) {
             resp.setHeader("Content-Type",typeMap.get("txt"));
-            if("clear".equals(cmd)) {
+            if ("clear".equals(key.substring(slash+1))) {
                 content.clear();
                 resp.setStatus(200/*HttpStatus.OK_200*/);
             } else {
@@ -170,8 +179,8 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             }
             return;
         }
-        Content c = load(logT , web_path,cmd!=null && cmd.length()>0?key+'/'+cmd:key, null, checkInterval);
-        if(c.attachmentOnly) {
+        Content c = load(logT , webPath,key, null, checkInterval);
+        if (c.attachmentOnly) {
             resp.setHeader("Content-disposition", "attachment");
         }
         c.setHeader(resp);
@@ -181,14 +190,14 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
 
 
     public String webPath() {
-        return web_path;
+        return webPath;
     }
-    
+
     /**
      * Reset the Cleanup size and interval
-     * 
+     *
      * The size and interval when started are 500 items (memory size unknown) checked every minute in a background thread.
-     * 
+     *
      * @param size
      * @param interval
      */
@@ -197,13 +206,13 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
         timer = new Timer();
         timer.schedule(new Cleanup(content,size), interval, interval);
     }
-    
 
-    
+
+
     /**
      * Load a file, first checking cache
-     * 
-     * 
+     *
+     *
      * @param logTarget - logTarget can be null (won't log)
      * @param dataRoot - data root storage directory
      * @param key - relative File Path
@@ -214,12 +223,12 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
      */
     public Content load(LogTarget logTarget, String dataRoot, String key, String mediaType, long _timeCheck) throws IOException {
         long timeCheck = _timeCheck;
-        if(timeCheck<0) {
+        if (timeCheck<0) {
             timeCheck=checkInterval; // if time < 0, then use default
         }
         boolean isRoot;
         String fileName;
-        if("-".equals(key)) {
+        if ("-".equals(key)) {
             fileName = dataRoot;
             isRoot = true;
         } else {
@@ -227,43 +236,43 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             isRoot = false;
         }
         Content c = content.get(key);
-        long systime = System.currentTimeMillis(); 
+        long systime = System.currentTimeMillis();
         File f=null;
-        if(c!=null) {
+        if (c!=null) {
             // Don't check every hit... only after certain time value
-            if(c.date < systime + timeCheck) {
+            if (c.date < systime + timeCheck) {
                 f = new File(fileName);
-                if(f.lastModified()>c.date) {
+                if (f.lastModified()>c.date) {
                     c=null;
                 }
             }
         }
-        if(c==null) {    
-            if(logTarget!=null) {
+        if (c==null) {
+            if (logTarget!=null) {
                 logTarget.log("File Read: ",key);
             }
-            
-            if(f==null){
+
+            if (f==null){
                 f = new File(fileName);
             }
             boolean cacheMe;
-            if(f.exists()) {
-                if(f.isDirectory()) {
+            if (f.exists()) {
+                if (f.isDirectory()) {
                     cacheMe = false;
                     c = new DirectoryContent(f,isRoot);
                 } else {
-                    if(f.length() > maxItemSize) {
+                    if (f.length() > maxItemSize) {
                         c = new DirectFileContent(f);
                         cacheMe = false;
                     } else {
                         c = new CachedContent(f);
                         cacheMe = checkInterval>0;
                     }
-                    
-                    if(mediaType==null) { // determine from file Ending
+
+                    if (mediaType==null) { // determine from file Ending
                         int idx = key.lastIndexOf('.');
                         String subkey = key.substring(++idx);
-                        if((c.contentType = idx<0?null:typeMap.get(subkey))==null) {
+                        if ((c.contentType = idx<0?null:typeMap.get(subkey))==null) {
                             // if nothing else, just set to default type...
                             c.contentType = "application/octet-stream";
                         }
@@ -272,10 +281,10 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
                         c.contentType=mediaType;
                         c.attachmentOnly = false;
                     }
-                    
+
                     c.date = f.lastModified();
-                    
-                    if(cacheMe) {
+
+                    if (cacheMe) {
                         content.put(key, c);
                     }
                 }
@@ -283,52 +292,25 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
                 c=NULL;
             }
         } else {
-            if(logTarget!=null)logTarget.log("Cache Read: ",key);
+            if (logTarget!=null)logTarget.log("Cache Read: ",key);
         }
 
         // refresh hit time
         c.access = systime;
         return c;
     }
-    
-    public Content loadOrDefault(Trans trans, String targetDir, String targetFileName, String sourcePath, String mediaType) throws IOException {
-        try {
-            return load(trans.info(),targetDir,targetFileName,mediaType,0);
-        } catch(FileNotFoundException e) {
-            String targetPath = targetDir + '/' + targetFileName;
-            TimeTaken tt = trans.start("File doesn't exist; copy " + sourcePath + " to " + targetPath, Env.SUB);
-            try {
-                FileInputStream sourceFIS = new FileInputStream(sourcePath);
-                FileChannel sourceFC = sourceFIS.getChannel();
-                File targetFile = new File(targetPath);
-                targetFile.getParentFile().mkdirs(); // ensure directory exists
-                FileOutputStream targetFOS = new FileOutputStream(targetFile);
-                try {
-                    ByteBuffer bb = ByteBuffer.allocate((int)sourceFC.size());
-                    sourceFC.read(bb);
-                    bb.flip();  // ready for reading
-                    targetFOS.getChannel().write(bb);
-                } finally {
-                    sourceFIS.close();
-                    targetFOS.close();
-                }
-            } finally {
-                tt.done();
-            }
-            return load(trans.info(),targetDir,targetFileName,mediaType,0);
-        }
-    }
+
 
     public void invalidate(String key) {
         content.remove(key);
     }
-    
+
     private static final Content NULL=new Content() {
-        
+
         @Override
         public void setHeader(HttpServletResponse resp) {
             resp.setStatus(404/*NOT_FOUND_404*/);
-            resp.setHeader("Content-type","text/plain");
+            resp.setHeader("Content-type",TEXT_PLAIN);
         }
 
         @Override
@@ -338,43 +320,43 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
         @Override
         public void write(OutputStream os) throws IOException {
         }
-        
+
     };
 
-    private static abstract class Content {
+    private abstract static class Content {
         private long date;   // date of the actual artifact (i.e. File modified date)
         private long access; // last accessed
-        
+
         protected String  contentType;
         protected boolean attachmentOnly;
-        
+
         public void setHeader(HttpServletResponse resp) {
             resp.setStatus(200/*OK_200*/);
             resp.setHeader("Content-Type",contentType);
-            resp.setHeader("Cache-Control", MAX_AGE);
+            resp.setHeader("Cache-Control", maxAge);
         }
-        
+
         public abstract void write(Writer writer) throws IOException;
         public abstract void write(OutputStream os) throws IOException;
 
     }
 
     private static class DirectFileContent extends Content {
-        private File file; 
+        private File file;
         public DirectFileContent(File f) {
             file = f;
         }
-        
+
         public String toString() {
             return file.getName();
         }
-        
+
         public void write(Writer writer) throws IOException {
             FileReader fr = new FileReader(file);
             char[] buff = new char[1024];
             try {
                 int read;
-                while((read = fr.read(buff,0,1024))>=0) {
+                while ((read = fr.read(buff,0,1024))>=0) {
                     writer.write(buff,0,read);
                 }
             } finally {
@@ -387,7 +369,7 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             byte[] buff = new byte[1024];
             try {
                 int read;
-                while((read = fis.read(buff,0,1024))>=0) {
+                while ((read = fis.read(buff,0,1024))>=0) {
                     os.write(buff,0,read);
                 }
             } finally {
@@ -407,7 +389,7 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
 
         public DirectoryContent(File directory, boolean isRoot) {
             notRoot = !isRoot;
-        
+
             files = directory.listFiles();
             Arrays.sort(files,new Comparator<File>() {
                 @Override
@@ -415,27 +397,27 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
                     // See if there are Numbers in the name
                     Matcher m1 = A_NUMBER.matcher(f1.getName());
                     Matcher m2 = A_NUMBER.matcher(f2.getName());
-                    if(m1.find() && m2.find()) {
+                    if (m1.find() && m2.find()) {
                         // if numbers, are the numbers in the same start position
                         int i1 = m1.start();
                         int i2 = m2.start();
-                        
+
                         // If same start position and the text is the same, then reverse sort
-                        if(i1==i2 && f1.getName().startsWith(f2.getName().substring(0,i1))) {
+                        if (i1==i2 && f1.getName().startsWith(f2.getName().substring(0,i1))) {
                             // reverse sort files that start similarly, but have numbers in them
                             return f2.compareTo(f1);
                         }
                     }
                     return f1.compareTo(f2);
                 }
-                
+
             });
             name = directory.getName();
             attachmentOnly = false;
             contentType = "text/html";
         }
-        
-    
+
+
         @Override
         public void write(Writer w) throws IOException {
             w.append(H1);
@@ -443,7 +425,7 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             w.append(H2);
             for (File f : files) {
                 w.append("<li><a href=\"");
-                if(notRoot) {
+                if (notRoot) {
                     w.append(name);
                     w.append('/');
                 }
@@ -455,19 +437,19 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             w.append(F);
             w.flush();
         }
-    
+
         @Override
         public void write(OutputStream os) throws IOException {
             write(new OutputStreamWriter(os));
         }
-    
+
     }
 
     private static class CachedContent extends Content {
         private byte[] data;
         private int end;
-        private char[] cdata; 
-        
+        private char[] cdata;
+
         public CachedContent(File f) throws IOException {
             // Read and Cache
             ByteBuffer bb = ByteBuffer.allocate((int)f.length());
@@ -482,15 +464,15 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
             end = bb.position();
             cdata=null;
         }
-        
+
         public String toString() {
             return Arrays.toString(data);
         }
-        
+
         public void write(Writer writer) throws IOException {
             synchronized(this) {
                 // do the String Transformation once, and only if actually used
-                if(cdata==null) {
+                if (cdata==null) {
                     cdata = new char[end];
                     new String(data).getChars(0, end, cdata, 0);
                 }
@@ -515,47 +497,41 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void
     private static class Cleanup extends TimerTask {
         private int maxSize;
         private NavigableMap<String, Content> content;
-        
+
         public Cleanup(NavigableMap<String, Content> content, int size) {
             maxSize = size;
             this.content = content;
         }
-        
+
         private class Comp implements Comparable<Comp> {
             public Map.Entry<String, Content> entry;
-            
+
             public Comp(Map.Entry<String, Content> en) {
                 entry = en;
             }
-            
+
             @Override
             public int compareTo(Comp o) {
                 return (int)(entry.getValue().access-o.entry.getValue().access);
             }
-            
+
         }
         @SuppressWarnings("unchecked")
         @Override
         public void run() {
             int size = content.size();
-            if(size>maxSize) {
+            if (size>maxSize) {
                 ArrayList<Comp> scont = new ArrayList<>(size);
                 Object[] entries = content.entrySet().toArray();
-                for(int i=0;i<size;++i) {
+                for (int i=0;i<size;++i) {
                     scont.add(i, new Comp((Map.Entry<String,Content>)entries[i]));
                 }
                 Collections.sort(scont);
                 int end = size - ((maxSize/4)*3); // reduce to 3/4 of max size
-                //System.out.println("------ Cleanup Cycle ------ " + new Date().toString() + " -------");
-                for(int i=0;i<end;++i) {
+                for (int i=0;i<end;++i) {
                     Entry<String, Content> entry = scont.get(i).entry;
                     content.remove(entry.getKey());
-                    //System.out.println("removed Cache Item " + entry.getKey() + "/" + new Date(entry.getValue().access).toString());
                 }
-//                for(int i=end;i<size;++i) {
-//                    Entry<String, Content> entry = scont.get(i).entry;
-//                    //System.out.println("remaining Cache Item " + entry.getKey() + "/" + new Date(entry.getValue().access).toString());
-//                }
             }
         }
     }