/*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* 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. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.linkedin.databus2.relay.config;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
/**
*
* Data structure that saves and retrieves relay configurations per physical source in the file system.
* This is not thread safe.
*
*/
public class DatabusRelaySourcesInFiles implements DatabusRelaySources
{
protected static final Logger LOG = Logger.getLogger(DatabusRelaySourcesInFiles.class.getName());
final HashMap<String,PhysicalSourceConfig> _configs;
final private String _dir;
/**
*
* @param sourceDir : a directory from which all .json files are interpreted to be serialized PhysicalSourcesConfig objects
* if directory does not exist an exception is thrown; if the path is a file; then an exception is thrown.
*
*/
public DatabusRelaySourcesInFiles(String sourceDir) throws Exception
{
File dir = new File(sourceDir);
if (dir.isDirectory())
{
_dir = sourceDir;
_configs = new HashMap<String,PhysicalSourceConfig> ();
}
else
{
throw new IOException("Source directory error: path= " + sourceDir + " exists=" + dir.exists() + " isDirectory=" + dir.isDirectory());
}
}
/**
* Given that _dir exists; either a source dir or
* @return list of files
*/
protected File[] getFiles()
{
File dir = new File(_dir);
File[] listFiles = dir.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.endsWith(".json") || name.endsWith(".JSON");
}
});
return listFiles;
}
protected ArrayList<PhysicalSourceConfig> getConfigs()
{
File[] listFiles = getFiles();
ArrayList<PhysicalSourceConfig> configs = new ArrayList<PhysicalSourceConfig> ();
for (File f:listFiles)
{
try
{
PhysicalSourceConfig pConfig = PhysicalSourceConfig.fromFile(f);
//not sure if this always returns an object; that's why the check is present
if (pConfig != null)
{
configs.add(pConfig);
}
else
{
LOG.warn("Unable to deserialize " + f.getAbsolutePath() + " Skipping!" );
}
}
catch (Exception e)
{
LOG.warn("Skipping file: " + f.getAbsolutePath() + " Exception: " + e.getMessage());
}
}
return configs;
}
@Override
public boolean add(String sourceName, PhysicalSourceConfig config)
{
if (!_configs.containsKey(sourceName))
{
_configs.put(sourceName, config);
return true;
}
LOG.warn("Source " + sourceName + " already exists! Not adding config. Please remove entry using remove()");
return false;
}
@Override
public PhysicalSourceConfig get(String sourceName)
{
return _configs.get(sourceName);
}
protected void clear()
{
_configs.clear();
}
public void removePersistedEntries()
{
File[] files = getFiles();
for (File f:files)
{
f.delete();
}
}
@Override
public boolean save()
{
boolean ret = true;
for (Entry<String,PhysicalSourceConfig> entry: _configs.entrySet())
{
String fileName = "sources-" + entry.getKey() + ".json";
String filePath = _dir + "/" + fileName;
if (entry.getValue()==null)
{
LOG.warn("Sourcename " + entry.getKey() + " has null value. Not persisting.");
}
else
{
try
{
FileOutputStream file = new FileOutputStream(filePath,false);
String val = entry.getValue().toString();
file.write(val.getBytes(Charset.defaultCharset()));
file.close();
}
catch (Exception e)
{
LOG.warn("Cannot save " + filePath + " for source " + entry.getKey());
ret = false;
}
}
}
return ret;
}
@Override
public boolean load()
{
clear();
ArrayList<PhysicalSourceConfig> configs = getConfigs();
for (PhysicalSourceConfig conf : configs)
{
add(conf.getName(),conf);
}
return true;
}
@Override
public boolean removeAll()
{
clear();
return true;
}
@Override
public PhysicalSourceConfig[] getAll()
{
PhysicalSourceConfig[] pConfigs = new PhysicalSourceConfig[_configs.size()];
int i=0;
for (Object o: _configs.values().toArray())
{
pConfigs[i++] = (PhysicalSourceConfig) o;
}
return pConfigs;
}
@Override
public boolean remove(String sourceName)
{
if (_configs.containsKey(sourceName))
{
_configs.remove(sourceName);
return true;
}
return false;
}
@Override
public int size()
{
return _configs.size();
}
}