X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=auth%2Fauth-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Faaf%2Fauth%2Frserv%2FCachingFileAccess.java;h=a269f24b09e6a4e59698514981cd70efd76d8dc8;hb=ff1417ff60baee231a28272f9a16ef2c9c8ea0a2;hp=7bb276a2403dcc6983b4e3f8267546d9d501f9d7;hpb=71037c39a37d3549dcfe31926832a657744fbe05;p=aaf%2Fauthz.git diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java index 7bb276a2..a269f24b 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java @@ -24,20 +24,16 @@ 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; import java.util.Comparator; -import java.util.Date; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; @@ -53,11 +49,9 @@ 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 @@ -66,499 +60,471 @@ import org.onap.aaf.misc.env.Trans; * */ public class CachingFileAccess extends HttpCode { - public static void setEnv(Store store, String[] args) { - for(int i=0;i typeMap; - private final NavigableMap content; - private final Set attachOnly; - public final static 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. - // 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"; + public static void setEnv(Store store, String[] args) { + for (int i=0;i typeMap; + private final NavigableMap content; + private final Set attachOnly; + public final static 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. + // 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"; - // Note: can be null without a problem, but included - // to tie in with existing Logging. - public LogTarget logT = null; - 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; - // 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 - // local batch files to, for instance, clear caches on resetting of files. - private String clear_command; - - public CachingFileAccess(EnvJAXB env, String ... args) throws IOException { - super(null,"Caching File Access"); - setEnv(env,args); - content = new ConcurrentSkipListMap(); // multi-thread changes possible + // Note: can be null without a problem, but included + // to tie in with existing Logging. + public LogTarget logT = null; + 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; + // 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 + // local batch files to, for instance, clear caches on resetting of files. + private String clear_command; + + public CachingFileAccess(EnvJAXB env, String ... args) throws IOException { + super(null,"Caching File Access"); + setEnv(env,args); + content = new ConcurrentSkipListMap<>(); // multi-thread changes possible - attachOnly = new HashSet(); // short, unchanged + attachOnly = new HashSet<>(); // short, unchanged - typeMap = new TreeMap(); // Structure unchanged after Construction - typeMap.put("ico","image/icon"); - typeMap.put("html","text/html"); - typeMap.put("css","text/css"); - typeMap.put("js","text/javascript"); - typeMap.put("txt","text/plain"); - typeMap.put("xml","text/xml"); - typeMap.put("xsd","text/xml"); - attachOnly.add("xsd"); - typeMap.put("crl", "application/x-pkcs7-crl"); - typeMap.put("appcache","text/cache-manifest"); + typeMap = new TreeMap<>(); // Structure unchanged after Construction + typeMap.put("ico","image/icon"); + typeMap.put("html","text/html"); + typeMap.put("css","text/css"); + typeMap.put("js","text/javascript"); + typeMap.put("txt","text/plain"); + typeMap.put("xml","text/xml"); + typeMap.put("xsd","text/xml"); + attachOnly.add("xsd"); + typeMap.put("crl", "application/x-pkcs7-crl"); + typeMap.put("appcache","text/cache-manifest"); - typeMap.put("json","text/json"); - typeMap.put("ogg", "audio/ogg"); - typeMap.put("jpg","image/jpeg"); - typeMap.put("gif","image/gif"); - typeMap.put("png","image/png"); - typeMap.put("svg","image/svg+xml"); - 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("jks", "application/octet-stream"); - - 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()); - 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);} - - 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); - } + typeMap.put("json","text/json"); + typeMap.put("ogg", "audio/ogg"); + typeMap.put("jpg","image/jpeg"); + typeMap.put("gif","image/gif"); + typeMap.put("png","image/png"); + typeMap.put("svg","image/svg+xml"); + 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("jks", "application/octet-stream"); + + 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()); + 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);} + + 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); + } - + - @Override - public void handle(TRANS trans, HttpServletRequest req, HttpServletResponse resp) throws IOException { - String key = pathParam(req, ":key"); - String cmd = pathParam(req,":cmd"); - System.out.print(key + clear_command); - if(key.equals(clear_command)) { - resp.setHeader("Content-Type",typeMap.get("txt")); - if("clear".equals(cmd)) { - content.clear(); - resp.setStatus(200/*HttpStatus.OK_200*/); - } else { - resp.setStatus(400/*HttpStatus.BAD_REQUEST_400 */); - } - return; - } - Content c = load(logT , web_path,cmd!=null && cmd.length()>0?key+'/'+cmd:key, null, checkInterval); - if(c.attachmentOnly) { - resp.setHeader("Content-disposition", "attachment"); - } - c.setHeader(resp); - c.write(resp.getOutputStream()); - trans.checkpoint(req.getPathInfo()); - } + @Override + public void handle(TRANS trans, HttpServletRequest req, HttpServletResponse resp) throws IOException { + String key = pathParam(req, ":key"); + int slash = key.indexOf('/'); + if(key.length()>2 && slash>=0 && key.substring(0,slash).equals(clear_command)) { + resp.setHeader("Content-Type",typeMap.get("txt")); + if ("clear".equals(key.substring(slash+1))) { + content.clear(); + resp.setStatus(200/*HttpStatus.OK_200*/); + } else { + resp.setStatus(400/*HttpStatus.BAD_REQUEST_400 */); + } + return; + } + Content c = load(logT , web_path,key, null, checkInterval); + if (c.attachmentOnly) { + resp.setHeader("Content-disposition", "attachment"); + } + c.setHeader(resp); + c.write(resp.getOutputStream()); + trans.checkpoint(req.getPathInfo()); + } - public String webPath() { - return web_path; - } - - /** - * 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 - */ - public void cleanupParams(int size, long interval) { - timer.cancel(); - timer = new Timer(); - timer.schedule(new Cleanup(content,size), interval, interval); - } - + public String webPath() { + return web_path; + } + + /** + * 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 + */ + public void cleanupParams(int size, long interval) { + timer.cancel(); + 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 - * @param mediaType - what kind of file is it. If null, will check via file extension - * @param timeCheck - "-1" will take system default - Otherwise, will compare "now" + timeCheck(Millis) before looking at File mod - * @return - * @throws IOException - */ - public Content load(LogTarget logTarget, String dataRoot, String key, String mediaType, long _timeCheck) throws IOException { - long timeCheck = _timeCheck; - if(timeCheck<0) { - timeCheck=checkInterval; // if time < 0, then use default - } - boolean isRoot; - String fileName; - if("-".equals(key)) { - fileName = dataRoot; - isRoot = true; - } else { - fileName=dataRoot + '/' + key; - isRoot = false; - } - Content c = content.get(key); - long systime = System.currentTimeMillis(); - File f=null; - if(c!=null) { - // Don't check every hit... only after certain time value - if(c.date < systime + timeCheck) { - f = new File(fileName); - if(f.lastModified()>c.date) { - c=null; - } - } - } - if(c==null) { - if(logTarget!=null) { - logTarget.log("File Read: ",key); - } - - if(f==null){ - f = new File(fileName); - } - boolean cacheMe; - if(f.exists()) { - if(f.isDirectory()) { - cacheMe = false; - c = new DirectoryContent(f,isRoot); - } else { - 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 - int idx = key.lastIndexOf('.'); - String subkey = key.substring(++idx); - if((c.contentType = idx<0?null:typeMap.get(subkey))==null) { - // if nothing else, just set to default type... - c.contentType = "application/octet-stream"; - } - c.attachmentOnly = attachOnly.contains(subkey); - } else { - c.contentType=mediaType; - c.attachmentOnly = false; - } - - c.date = f.lastModified(); - - if(cacheMe) { - content.put(key, c); - } - } - } else { - c=NULL; - } - } else { - if(logTarget!=null)logTarget.log("Cache Read: ",key); - } + + /** + * 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 + * @param mediaType - what kind of file is it. If null, will check via file extension + * @param timeCheck - "-1" will take system default - Otherwise, will compare "now" + timeCheck(Millis) before looking at File mod + * @return + * @throws IOException + */ + public Content load(LogTarget logTarget, String dataRoot, String key, String mediaType, long _timeCheck) throws IOException { + long timeCheck = _timeCheck; + if (timeCheck<0) { + timeCheck=checkInterval; // if time < 0, then use default + } + boolean isRoot; + String fileName; + if ("-".equals(key)) { + fileName = dataRoot; + isRoot = true; + } else { + fileName=dataRoot + '/' + key; + isRoot = false; + } + Content c = content.get(key); + long systime = System.currentTimeMillis(); + File f=null; + if (c!=null) { + // Don't check every hit... only after certain time value + if (c.date < systime + timeCheck) { + f = new File(fileName); + if (f.lastModified()>c.date) { + c=null; + } + } + } + if (c==null) { + if (logTarget!=null) { + logTarget.log("File Read: ",key); + } + + if (f==null){ + f = new File(fileName); + } + boolean cacheMe; + if (f.exists()) { + if (f.isDirectory()) { + cacheMe = false; + c = new DirectoryContent(f,isRoot); + } else { + 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 + int idx = key.lastIndexOf('.'); + String subkey = key.substring(++idx); + if ((c.contentType = idx<0?null:typeMap.get(subkey))==null) { + // if nothing else, just set to default type... + c.contentType = "application/octet-stream"; + } + c.attachmentOnly = attachOnly.contains(subkey); + } else { + c.contentType=mediaType; + c.attachmentOnly = false; + } + + c.date = f.lastModified(); + + if (cacheMe) { + content.put(key, c); + } + } + } else { + c=NULL; + } + } else { + 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); - } - } + // refresh hit time + c.access = systime; + return c; + } + - 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"); - } + 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"); + } - @Override - public void write(Writer writer) throws IOException { - } + @Override + public void write(Writer writer) throws IOException { + } - @Override - public void write(OutputStream os) throws IOException { - } - - }; + @Override + public void write(OutputStream os) throws IOException { + } + + }; - private static abstract 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); - } - - public abstract void write(Writer writer) throws IOException; - public abstract void write(OutputStream os) throws IOException; + private static abstract 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); + } + + 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; - 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) { - writer.write(buff,0,read); - } - } finally { - fr.close(); - } - } + private static class DirectFileContent extends Content { + 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) { + writer.write(buff,0,read); + } + } finally { + fr.close(); + } + } - public void write(OutputStream os) throws IOException { - FileInputStream fis = new FileInputStream(file); - byte[] buff = new byte[1024]; - try { - int read; - while((read = fis.read(buff,0,1024))>=0) { - os.write(buff,0,read); - } - } finally { - fis.close(); - } - } + public void write(OutputStream os) throws IOException { + FileInputStream fis = new FileInputStream(file); + byte[] buff = new byte[1024]; + try { + int read; + while ((read = fis.read(buff,0,1024))>=0) { + os.write(buff,0,read); + } + } finally { + fis.close(); + } + } - } - private static class DirectoryContent extends Content { - private static final Pattern A_NUMBER = Pattern.compile("\\d"); - private static final String H1 = "AAF Fileserver

AAF Fileserver

"; - private static final String H2 = "

    \n"; - private static final String F = "\n
"; - private File[] files; - private String name; - private boolean notRoot; + } + private static class DirectoryContent extends Content { + private static final Pattern A_NUMBER = Pattern.compile("\\d"); + private static final String H1 = "AAF Fileserver

AAF Fileserver

"; + private static final String H2 = "

    \n"; + private static final String F = "\n
"; + private File[] files; + private String name; + private boolean notRoot; - public DirectoryContent(File directory, boolean isRoot) { - notRoot = !isRoot; - - files = directory.listFiles(); - Arrays.sort(files,new Comparator() { - @Override - public int compare(File f1, File f2) { - // 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 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))) { - // 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); - w.append(name); - w.append(H2); - for (File f : files) { - w.append("
  • "); - w.append(f.getName()); - w.append("
  • \n"); - } - w.append(F); - w.flush(); - } - - @Override - public void write(OutputStream os) throws IOException { - write(new OutputStreamWriter(os)); - } - - } + public DirectoryContent(File directory, boolean isRoot) { + notRoot = !isRoot; + + files = directory.listFiles(); + Arrays.sort(files,new Comparator() { + @Override + public int compare(File f1, File f2) { + // 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 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))) { + // 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); + w.append(name); + w.append(H2); + for (File f : files) { + w.append("
  • "); + w.append(f.getName()); + w.append("
  • \n"); + } + 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; - - public CachedContent(File f) throws IOException { - // Read and Cache - ByteBuffer bb = ByteBuffer.allocate((int)f.length()); - FileInputStream fis = new FileInputStream(f); - try { - fis.getChannel().read(bb); - } finally { - fis.close(); - } + private static class CachedContent extends Content { + private byte[] data; + private int end; + private char[] cdata; + + public CachedContent(File f) throws IOException { + // Read and Cache + ByteBuffer bb = ByteBuffer.allocate((int)f.length()); + FileInputStream fis = new FileInputStream(f); + try { + fis.getChannel().read(bb); + } finally { + fis.close(); + } - data = bb.array(); - end = bb.position(); - cdata=null; - } - - public String toString() { - return data.toString(); - } - - public void write(Writer writer) throws IOException { - synchronized(this) { - // do the String Transformation once, and only if actually used - if(cdata==null) { - cdata = new char[end]; - new String(data).getChars(0, end, cdata, 0); - } - } - writer.write(cdata,0,end); - } - public void write(OutputStream os) throws IOException { - os.write(data,0,end); - } + data = bb.array(); + 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) { + cdata = new char[end]; + new String(data).getChars(0, end, cdata, 0); + } + } + writer.write(cdata,0,end); + } + public void write(OutputStream os) throws IOException { + os.write(data,0,end); + } - } + } - public void setEnv(LogTarget env) { - logT = env; - } + public void setEnv(LogTarget env) { + logT = env; + } - /** - * Cleanup thread to remove older items if max Cache is reached. - * @author Jonathan - * - */ - private static class Cleanup extends TimerTask { - private int maxSize; - private NavigableMap content; - - public Cleanup(NavigableMap content, int size) { - maxSize = size; - this.content = content; - } - - private class Comp implements Comparable { - public Map.Entry entry; - - public Comp(Map.Entry 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) { - ArrayList scont = new ArrayList(size); - Object[] entries = content.entrySet().toArray(); - for(int i=0;i)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 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 entry = scont.get(i).entry; - System.out.println("remaining Cache Item " + entry.getKey() + "/" + new Date(entry.getValue().access).toString()); - } - } - } - } + /** + * Cleanup thread to remove older items if max Cache is reached. + * @author Jonathan + * + */ + private static class Cleanup extends TimerTask { + private int maxSize; + private NavigableMap content; + + public Cleanup(NavigableMap content, int size) { + maxSize = size; + this.content = content; + } + + private class Comp implements Comparable { + public Map.Entry entry; + + public Comp(Map.Entry 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) { + ArrayList scont = new ArrayList<>(size); + Object[] entries = content.entrySet().toArray(); + for (int i=0;i)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 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 entry = scont.get(i).entry; +// //System.out.println("remaining Cache Item " + entry.getKey() + "/" + new Date(entry.getValue().access).toString()); +// } + } + } + } }