/*******************************************************************************
* Copyright (c) 2010, 2016 Nicolas Roduit.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
******************************************************************************/
package org.weasis.core.api.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.felix.prefs.BackingStoreManager;
import org.apache.felix.prefs.PreferencesDescription;
import org.apache.felix.prefs.PreferencesImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.weasis.core.api.gui.util.AppProperties;
import org.weasis.core.api.util.FileUtil;
public class DataFileBackingStoreImpl extends StreamBackingStoreImpl {
private static final Logger LOGGER = LoggerFactory.getLogger(DataFileBackingStoreImpl.class);
private final BundleContext context;
private final File prefRootDirectory;
public DataFileBackingStoreImpl(BundleContext context) {
super(context);
this.context = context;
StringBuilder bufDir = new StringBuilder(AppProperties.WEASIS_PATH);
bufDir.append(File.separator);
bufDir.append("preferences"); //$NON-NLS-1$
bufDir.append(File.separator);
bufDir.append(AppProperties.WEASIS_USER);
bufDir.append(File.separator);
bufDir.append(AppProperties.WEASIS_PROFILE);
this.prefRootDirectory = new File(bufDir.toString());
prefRootDirectory.mkdirs();
}
/**
* @see org.apache.felix.sandbox.preferences.impl.StreamBackingStoreImpl#checkAccess()
*/
@Override
protected void checkAccess() throws BackingStoreException {
if (prefRootDirectory == null || !prefRootDirectory.exists()) {
throw new BackingStoreException("Saving of data files to the bundle context is currently not supported."); //$NON-NLS-1$
}
}
/**
* @see org.apache.felix.sandbox.preferences.impl.StreamBackingStoreImpl#getOutputStream(org.apache.felix.sandbox.preferences.PreferencesDescription)
*/
@Override
protected OutputStream getOutputStream(PreferencesDescription desc) throws IOException {
File file = this.getFile(desc);
// Write user folder if not exists
FileUtil.prepareToWriteFile(file);
return new FileOutputStream(file);
}
/**
* @see org.apache.felix.prefs.BackingStore#availableBundles()
*/
@Override
public Long[] availableBundles() {
return new Long[0];
}
protected PreferencesDescription getDescription(File file) {
final String fileName = file.getName();
// parse the file name to get: bundle id, user|system identifier
if (fileName.endsWith(".xml")) { //$NON-NLS-1$
final String key = fileName.substring(0, fileName.length() - 4);
Bundle[] bundles = context.getBundles();
for (Bundle bundle : bundles) {
if (bundle.getSymbolicName().equals(key)) {
return new PreferencesDescription(bundle.getBundleId(), AppProperties.WEASIS_USER);
}
}
}
return null;
}
/**
* @see org.apache.felix.prefs.BackingStore#remove(java.lang.Long)
*/
@Override
public void remove(Long bundleId) throws BackingStoreException {
// Do nothing, we don't want to delete the preferences file when a bundle is uninstalled
}
/**
* @see org.apache.felix.prefs.BackingStore#loadAll(org.apache.felix.prefs.BackingStoreManager, java.lang.Long)
*/
@Override
public PreferencesImpl[] loadAll(BackingStoreManager manager, Long bundleId) throws BackingStoreException {
this.checkAccess();
PreferencesImpl pref = load(manager, new PreferencesDescription(bundleId, AppProperties.WEASIS_USER));
return pref == null ? new PreferencesImpl[0] : new PreferencesImpl[] { pref };
}
/**
* @see org.apache.felix.prefs.BackingStore#load(org.apache.felix.prefs.BackingStoreManager,
* org.apache.felix.prefs.PreferencesDescription)
*/
@Override
public PreferencesImpl load(BackingStoreManager manager, PreferencesDescription desc) throws BackingStoreException {
this.checkAccess();
final File file = this.getFile(desc);
if (file != null && file.exists()) {
XMLStreamReader xmler = null;
FileInputStream fileReader = null;
try {
final PreferencesImpl root = new PreferencesImpl(desc, manager);
XMLInputFactory xmlif = XMLInputFactory.newInstance();
fileReader = new FileInputStream(file);
xmler = xmlif.createXMLStreamReader(fileReader);
int eventType;
while (xmler.hasNext()) {
eventType = xmler.next();
switch (eventType) {
case XMLStreamConstants.START_ELEMENT:
String key = xmler.getName().getLocalPart();
if ("preferences".equals(key)) { //$NON-NLS-1$
while (xmler.hasNext()) {
eventType = xmler.next();
switch (eventType) {
// It is a child of the preferences node
case XMLStreamConstants.START_ELEMENT:
this.read(root, xmler, xmler.getName().getLocalPart());
break;
default:
break;
}
}
}
break;
default:
break;
}
}
root.getChangeSet().clear();
return root;
}
catch (XMLStreamException e) {
LOGGER.error("Cannot read Preferences file", e); //$NON-NLS-1$
throw new BackingStoreException("Unable to load preferences.", e); //$NON-NLS-1$
} catch (FileNotFoundException e) {
throw new BackingStoreException("Unable to load preferences.", e); //$NON-NLS-1$
} finally {
FileUtil.safeClose(xmler);
FileUtil.safeClose(fileReader);
}
}
return null;
}
/**
* Get the file for the preferences tree.
*
* @param desc
* @return the preference file
*/
protected File getFile(PreferencesDescription desc) {
Bundle bundle = context.getBundle(desc.getBundleId());
if (bundle == null) {
return null;
}
return new File(this.prefRootDirectory, bundle.getSymbolicName() + ".xml"); //$NON-NLS-1$
}
}