Package org.pentaho.reporting.designer.core.settings.prefs

Source Code of org.pentaho.reporting.designer.core.settings.prefs.BinaryPreferences

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.designer.core.settings.prefs;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel;
import org.pentaho.reporting.libraries.base.util.DebugLog;

/**
* Todo: Document Me
*
* @author Thomas Morgner
*/
public class BinaryPreferences extends AbstractPreferences
{
  private static final Log logger = LogFactory.getLog(BinaryPreferences.class);
  private Properties properties;
  private BinaryPreferences parent;
  private long lastModificationTime;
  private String rootPath;

  public BinaryPreferences(final String rootPath)
  {
    super(null, "");
    this.rootPath = rootPath;
  }

  public BinaryPreferences(final BinaryPreferences parent, final String name)
  {
    super(parent, name);
    this.parent = parent;
    this.properties = new Properties();
  }

  protected void putSpi(final String key, final String value)
  {
    initCache();
    properties.setProperty(key, value);
    lastModificationTime = Math.max (lastModificationTime + 1, System.currentTimeMillis());
    try
    {
      flush();
    }
    catch (BackingStoreException e)
    {
      if (logger.isInfoEnabled())
      {
        logger.info("Failed to flush configuration changes");//NON-NLS
      }
      else if (logger.isDebugEnabled())
      {
        logger.info("Failed to flush configuration changes",e);//NON-NLS
      }
    }
  }

  private void initCache()
  {
    if (lastModificationTime == 0)
    {
      final File pathForNode = new File(getPathForNode());
      try
      {
        load(pathForNode);
      }
      catch (BackingStoreException e)
      {
        logger.warn("Failed to load data", e);//NON-NLS
        // ignored
      }
    }
  }

  protected String getSpi(final String key)
  {
    initCache();
    return properties.getProperty(key);
  }

  protected void removeSpi(final String key)
  {
    initCache();
    properties.remove(key);
    lastModificationTime = Math.max (lastModificationTime + 1, System.currentTimeMillis());
    try
    {
      flush();
    }
    catch (BackingStoreException e)
    {
      if (logger.isInfoEnabled())
      {
        logger.info("Failed to flush configuration changes");//NON-NLS
      }
      else if (logger.isDebugEnabled())
      {
        logger.info("Failed to flush configuration changes", e);//NON-NLS
      }
    }
  }

  public long getLastModificationTime()
  {
    return lastModificationTime;
  }

  protected String[] keysSpi() throws BackingStoreException
  {
    initCache();
    return (String[]) properties.keySet().toArray(new String[properties.size()]);
  }

  protected String[] childrenNamesSpi() throws BackingStoreException
  {
    final ArrayList<String> result = new ArrayList<String>();
    final File pathForNode = new File(getPathForNode());
    final File[] dirContents = pathForNode.listFiles();
    if (dirContents != null)
    {
      for (int i = 0; i < dirContents.length; i++)
      {
        if (dirContents[i].isDirectory())
        {
          result.add(decodePath(dirContents[i].getName()));
        }
      }
    }
    return result.toArray(new String[result.size()]);
  }

  protected AbstractPreferences childSpi(final String name)
  {
    if (name == null || name.length() == 0)
    {
      throw new IllegalArgumentException();
    }

    return new BinaryPreferences(this, name);
  }

  protected void syncSpi() throws BackingStoreException
  {
    final File pathForNode = new File(getPathForNode());
    if (pathForNode.exists() == false && properties.isEmpty())
    {
      return;
    }

    load(pathForNode);

    if (pathForNode.exists() == false)
    {
      if (pathForNode.mkdirs() == false)
      {
        throw new BackingStoreException("Failed to write config " + pathForNode); //$NON-NLS-1$
      }
    }

    final File target = new File(pathForNode, "prefs.properties");//NON-NLS
    if (target.exists() == false || target.lastModified() < lastModificationTime)
    {
      try
      {
        final OutputStream out = new BufferedOutputStream(new FileOutputStream(target));
        try
        {
          properties.store(out, "");
        }
        finally
        {
          out.close();
        }
      }
      catch (final Exception e)
      {
        throw new BackingStoreException("Failed to write config " + target); //$NON-NLS-1$
      }
    }
  }

  private void load(final File pathForNode)
      throws BackingStoreException
  {
    if (pathForNode.exists())
    {
      // load ..
      final File target = new File(pathForNode, "prefs.properties");//NON-NLS
      if (target.lastModified() > lastModificationTime)
      {
        if (target.exists())
        {
          try
          {
            final InputStream out = new BufferedInputStream(new FileInputStream(target));
            try
            {
              properties.clear();
              properties.load(out);
              lastModificationTime = Math.max (lastModificationTime + 1, System.currentTimeMillis());
            }
            finally
            {
              out.close();
            }
          }
          catch (final Exception e)
          {
            UncaughtExceptionsModel.getInstance().addException(e);
            throw new BackingStoreException("Failed to write config " + target); //$NON-NLS-1$
          }
        }
      }
    }
  }

  protected void flushSpi() throws BackingStoreException
  {
    // no-op
    syncSpi();
  }


  protected void removeNodeSpi() throws BackingStoreException
  {
    // delete the directory ..
    final File pathForNode = new File(getPathForNode());
    if (pathForNode.exists())
    {
      final File target = new File(pathForNode, "prefs.properties");//NON-NLS
      if (target.delete() == false)
      {
        throw new BackingStoreException("Unable to delete node-backend");
      }
      if (pathForNode.delete() == false)
      {
        throw new BackingStoreException("Unable to delete node-backend");
      }
    }
  }

  private String getPathForNode()
  {
    if (parent != null)
    {
      return parent.getPathForNode() + File.separatorChar + encodePath(name());
    }

    return rootPath;
  }


  /**
   * Encodes the given configuration path. All non-ascii characters get replaced by an escape sequence.
   *
   * @param path the path.
   * @return the translated path.
   * @throws java.util.prefs.BackingStoreException if something goes wrong.
   */
  private static String decodePath(final String path) throws BackingStoreException
  {
    try
    {
      final char[] data = path.toCharArray();
      final StringBuffer encoded = new StringBuffer(path.length());
      int seenDollarIndex = -1;
      for (int i = 0; i < data.length; i++)
      {
        if (seenDollarIndex > -1)
        {
          if (data[i] == '$')
          {
            encoded.append('$');
            seenDollarIndex = -1;
            continue;
          }

          if (i - seenDollarIndex == 4)
          {
            final int c = Integer.parseInt(path.substring(seenDollarIndex + 1, i + 1), 16);
            encoded.append((char) c);
            seenDollarIndex = -1;
            continue;
          }
          else
          {
            continue;
          }
        }

        if (data[i] == '$')
        {
          seenDollarIndex = i;
        }
        else
        {
          encoded.append(data[i]);
        }
      }
      return encoded.toString();
    }
    catch (NumberFormatException nfe)
    {
      nfe.printStackTrace();
      throw new BackingStoreException("Failed to decode name: " + path);
    }
  }

  /**
   * Encodes the given configuration path. All non-ascii characters get replaced by an escape sequence.
   *
   * @param path the path.
   * @return the translated path.
   */
  private static String encodePath(final String path)
  {
    final char[] data = path.toCharArray();
    final StringBuffer encoded = new StringBuffer(path.length());
    for (int i = 0; i < data.length; i++)
    {
      if (data[i] == '$')
      {
        // double quote
        encoded.append('$');
        encoded.append('$');
      }
      else if (Character.isJavaIdentifierPart(data[i]) == false)
      {
        // padded hex string
        encoded.append('$');
        final String hex = Integer.toHexString(data[i]);
        for (int x = hex.length(); x < 4; x++)
        {
          encoded.append('0');
        }
        encoded.append(hex);
      }
      else
      {
        encoded.append(data[i]);
      }
    }
    return encoded.toString();
  }

}
TOP

Related Classes of org.pentaho.reporting.designer.core.settings.prefs.BinaryPreferences

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.