Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  
  /*
   * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. Use is
   * subject to license terms.
   */ 
  
  package org.jdesktop.application;
  
  import java.awt.Rectangle;
 import java.io.File;
 import java.net.URL;
 import  javax.jnlp.BasicService;
 import  javax.jnlp.FileContents;
 import  javax.jnlp.PersistenceService;
 import  javax.jnlp.ServiceManager;
 import  javax.jnlp.UnavailableServiceException;


Access to per application, per user, local file storage.

Author(s):
Hans Muller (Hans.Muller@Sun.COM)
See also:
ApplicationContext.getLocalStorage
SessionStorage
 
 public class LocalStorage extends AbstractBean {
     private static Logger logger = Logger.getLogger(LocalStorage.class.getName());
     private final ApplicationContext context;    
     private long storageLimit = -1L;
     private LocalIO localIO = null;
     private final File unspecifiedFile = new File("unspecified");
     private File directory = ;
 
     protected LocalStorage(ApplicationContext context) {
         if (context == null) {
             throw new IllegalArgumentException("null context");
         }
         this. = context;
     }
 
     // FIXME - documentation
     protected final ApplicationContext getContext() {
         return ;
     }
 
     private void checkFileName(String fileName) {
 	if (fileName == null) {
 	    throw new IllegalArgumentException("null fileName");
 	}
     }
 
     public InputStream openInputFile(String fileNamethrows IOException {
 	checkFileName(fileName);
 	return getLocalIO().openInputFile(fileName);
     }
 
     public OutputStream openOutputFile(String fileNamethrows IOException {
 	checkFileName(fileName);
 	return getLocalIO().openOutputFile(fileName);
     }
 
     public boolean deleteFile(String fileNamethrows IOException {
 	checkFileName(fileName);
 	return getLocalIO().deleteFile(fileName);
     }
 
     /* If an exception occurs in the XMLEncoder/Decoder, we want
      * to throw an IOException.  The exceptionThrow listener method
      * doesn't throw a checked exception so we just set a flag
      * here and check it when the encode/decode operation finishes
      */
     private static class AbortExceptionListener implements ExceptionListener {
 	public Exception exception = null;
 	public void exceptionThrown(Exception e) {
 	    if ( == null) {  = e; }
 	}
     }
    private static boolean persistenceDelegatesInitialized = false;
    
    public void save(Object beanfinal String fileNamethrows IOException {
	XMLEncoder e = null;
	/* Buffer the XMLEncoder's output so that decoding errors don't
	 * cause us to trash the current version of the specified file.
	 */
	try {
	    e = new XMLEncoder(bst);
            if (!) {
                e.setPersistenceDelegate(Rectangle.classnew RectanglePD());
                 = true;
            }
	    e.setExceptionListener(el);
	    e.writeObject(bean);
	}
	finally {
	    if (e != null) { e.close(); }
	}
	if (el.exception != null) {
	    throw new LSException("save failed \"" + fileName + "\""el.exception);
	}
	OutputStream ost = null;
	try {
	    ost = openOutputFile(fileName);
	    ost.write(bst.toByteArray());
	}
	finally {
	    if (ost != null) { ost.close(); }
	}
    }
    public Object load(String fileNamethrows IOException {
	InputStream ist = null
	try {
	    ist = openInputFile(fileName);
	}
	catch(IOException e) {
	    return null;
	}
	XMLDecoder d = null;	
	try {
	    d = new XMLDecoder(ist);
	    d.setExceptionListener(el);
	    Object bean = d.readObject();
	    if (el.exception != null) {
		throw new LSException("load failed \"" + fileName + "\""el.exception);
	    }
	    return bean;
	}
	finally {
	    if (d != null) { d.close(); }
	}
    }
    private void closeStream(Closeable stString fileNamethrows IOException {
	if (st != null) { 
	    try { st.close(); } 
	    catch (java.io.IOException e) { 
		throw new LSException("close failed \"" + fileName + "\""e);
	    }
	}
    }
    public long getStorageLimit() {
	return ;
    }
    public void setStorageLimit(long storageLimit) {
	if (storageLimit < -1L) {
	    throw new IllegalArgumentException("invalid storageLimit");
	}
	long oldValue = this.;
	this. = storageLimit;
	firePropertyChange("storageLimit"oldValuethis.);
    }
    private String getId(String keyString def) {
	ResourceMap appResourceMap = getContext().getResourceMap();
	String id = appResourceMap.getString(key);
	if (id == null) {
	    .log(."unspecified resource "+key+" using "+def);
	    id = def;
	}
	else if (id.trim().length() == 0) {
	    .log(."empty resource "+key+" using "+def);	
	    id = def;
	}
	return id;
    }
    private String getApplicationId() { 
	return getId("Application.id"getContext().getApplicationClass().getSimpleName()); 
    }
    private String getVendorId() { 
	return getId("Application.vendorId""UnknownApplicationVendor"); 
    }
    /* The following enum and method only exist to distinguish 
     * Windows and OSX for the sake of getDirectory().
     */
    private enum OSId { WINDOWS, OSX, UNIX }
    private OSId getOSId() {
	PrivilegedAction<StringdoGetOSName = new PrivilegedAction<String>() {
	    public String run() {
		return System.getProperty("os.name");
	    }
	};
	OSId id = .;
	String osName = AccessController.doPrivileged(doGetOSName);
	if (osName != null) {
	    if (osName.toLowerCase().startsWith("mac os x")) {
		id = .;
	    }
	    else if (osName.contains("Windows")) {
		id = .;
	    }
	}
	return id;
    }
    public File getDirectory() {
	     = null;
	    String userHome = null;
	    try { 
		userHome = System.getProperty("user.home");   
	    }
	    catch(SecurityException ignore) { 
	    }
	    if (userHome != null) {
		String applicationId = getApplicationId();
		OSId osId = getOSId();
		if (osId == .) {
		    File appDataDir = null;
		    try {
			String appDataEV = System.getenv("APPDATA");
			if ((appDataEV != null) && (appDataEV.length() > 0)) {
			    appDataDir = new File(appDataEV);
			}
		    }
		    catch(SecurityException ignore) { 
		    }			
		    String vendorId = getVendorId();
		    if ((appDataDir != null) && appDataDir.isDirectory()) {
			// ${APPDATA}\{vendorId}\${applicationId}
			String path = vendorId + "\\" + applicationId + "\\";
			 = new File(appDataDirpath);
		    }
		    else {
			// ${userHome}\Application Data\${vendorId}\${applicationId}
			String path = "Application Data\\" + vendorId + "\\" + applicationId + "\\";
			 = new File(userHomepath);
		    }
		}
		else if (osId == .) {
		    // ${userHome}/Library/Application Support/${applicationId}
		    String path = "Library/Application Support/"+applicationId+"/";
		     = new File(userHomepath);
		}
		else {
		    // ${userHome}/.${applicationId}/
		    String path = "."+applicationId+"/";
		     = new File(userHomepath);
		}
	    }
	}
	return ;
    }
    public void setDirectory(File directory) {
	File oldValue = this.;
	this. = directory;
	firePropertyChange("directory"oldValuethis.);
    }
    /* Papers over the fact that the String,Throwable IOException 
     * constructor was only introduced in Java 6.
     */
    private static class LSException extends IOException {
	public LSException(String sThrowable e) {
	    super(s);
	    initCause(e);
	}
	public LSException(String s) {
	    super(s);
	}
    }
    /* There are some (old) Java classes that aren't proper beans.  Rectangle
     * is one of these.  When running within the secure sandbox, writing a 
     * Rectangle with XMLEncoder causes a security exception because 
     * DefaultPersistenceDelegate calls Field.setAccessible(true) to gain
     * access to private fields.  This is a workaround for that problem.
     * A bug has been filed, see JDK bug ID 4741757  
     */
    private static class RectanglePD extends DefaultPersistenceDelegate {
	public RectanglePD() {
	    super(new String[]{"x""y""width""height"});
	}
	protected Expression instantiate(Object oldInstanceEncoder out) {
	    Rectangle oldR = (Rectangle)oldInstance;
	    Object[] constructorArgs = new Object[]{
		oldR.xoldR.yoldR.widtholdR.height
	    };
	    return new Expression(oldInstanceoldInstance.getClass(), "new"constructorArgs);
	}
    }
    private synchronized LocalIO getLocalIO() {
	if ( == null) {
	    if ( == null) {
		 = new LocalFileIO();
	    }
	}
	return ;
    }
    private abstract class LocalIO {
	public abstract InputStream openInputFile(String fileNamethrows IOException;
	public abstract OutputStream openOutputFile(String fileNamethrows IOException;
	public abstract boolean deleteFile(String fileNamethrows IOException;
    }
    private class LocalFileIO extends LocalIO {
	public InputStream openInputFile(String fileNamethrows IOException {
	    File path = new File(getDirectory(), fileName);
	    try {
		return new BufferedInputStream(new FileInputStream(path));
	    }
	    catch (IOException e) {
		throw new LSException("couldn't open input file \"" + fileName + "\""e);
	    }
	}
	public OutputStream openOutputFile(String fileNamethrows IOException {
	    File dir = getDirectory();
	    if (!dir.isDirectory()) {
		if (!dir.mkdirs()) {
		    throw new LSException("couldn't create directory " + dir);
		}
	    }
	    File path = new File(dirfileName);
	    try {
		return new BufferedOutputStream(new FileOutputStream(path));
	    }
	    catch (IOException e) {
		throw new LSException("couldn't open output file \"" + fileName + "\""e);
	    }
	}
	public boolean deleteFile(String fileNamethrows IOException {
	    File path = new File(getDirectory(), fileName);
	    return path.delete();
	}
    }
    /* Determine if we're a web started application and the
     * JNLP PersistenceService is available without forcing
     * the JNLP API to be class-loaded.  We don't want to 
     * require apps that aren't web started to bundle javaws.jar
     */
    private LocalIO getPersistenceServiceIO() {
	try {
	    Class smClass = Class.forName("javax.jnlp.ServiceManager");
	    Method getServiceNamesMethod = smClass.getMethod("getServiceNames");
	    String[] serviceNames = (String[])getServiceNamesMethod.invoke(null);
	    boolean psFound = false;
	    boolean bsFound = false;
	    for(String serviceName : serviceNames) {
		if (serviceName.equals("javax.jnlp.BasicService")) {
		    bsFound = true;
		}
		else if (serviceName.equals("javax.jnlp.PersistenceService")) {
		    psFound = true;
		}
	    }
	    if (bsFound && psFound) {
		return new PersistenceServiceIO();
	    }
	}
	catch (Exception ignore) {
	    // either the classes or the services can't be found
	}
	return null;
    }
    private class PersistenceServiceIO extends LocalIO {
	private BasicService bs;
	private PersistenceService ps;
	    return getClass().getName() + " initialization failed: " + s;
	}
	    try {
		 = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
		 = (PersistenceService)ServiceManager.lookup("javax.jnlp.PersistenceService");
	    }
	    catch (UnavailableServiceException e) {
		.log(.initFailedMessage("ServiceManager.lookup"), e);
		 = null = null;
	    }
	}
	private void checkBasics(String sthrows IOException {
	    if (( == null) || ( == null)) {
	    }
	}
	private URL fileNameToURL(String namethrows IOException {
	    try {
		return new URL(.getCodeBase(), name);
	    }
	    catch (MalformedURLException e) {
		throw new LSException("invalid filename \"" + name + "\""e);
	    }
	}
	public InputStream openInputFile(String fileNamethrows IOException {
	    checkBasics("openInputFile");
	    URL fileURL = fileNameToURL(fileName);
	    try {
		return new BufferedInputStream(.get(fileURL).getInputStream());
	    } 
	    catch(Exception e) {
		throw new LSException("openInputFile \"" + fileName + "\" failed"e);
	    }
	}
	public OutputStream openOutputFile(String fileNamethrows IOException {
	    checkBasics("openOutputFile");
	    URL fileURL = fileNameToURL(fileName);
	    try {
		FileContents fc = null;
		try {
		    fc = .get(fileURL);  
		}
		catch (FileNotFoundException e) {
		    /* Verify that the max size for new PersistenceService 
		     * files is >= 100K (2^17) before opening one.
		     */
		    long maxSizeRequest = 131072L;
		    long maxSize = .create(fileURLmaxSizeRequest);
		    if (maxSize >= maxSizeRequest) {
			fc = .get(fileURL);
		    }
		}
		if ((fc != null) && (fc.canWrite())) {
		    return new BufferedOutputStream(fc.getOutputStream(true));
		}
		else {
		    throw new IOException("unable to create FileContents object");
		}
	    } 
	    catch(Exception e) {
		throw new LSException("openOutputFile \"" + fileName + "\" failed"e);
	    }
	}
	public boolean deleteFile(String fileNamethrows IOException {
	    checkBasics("deleteFile");
	    URL fileURL = fileNameToURL(fileName);
	    try {
		.delete(fileURL);
                return true;
	    } 
	    catch(Exception e) {
		throw new LSException("openInputFile \"" + fileName + "\" failed"e);
	    }
	}
    }
New to GrepCode? Check out our FAQ X