/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2008, 2009, 2010, 2011 Palo Alto Research Center, Inc.
*
* This library 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.
* This library 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. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.impl.repo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.KeyManager;
import org.ccnx.ccn.impl.CCNFlowControl.SaveType;
import org.ccnx.ccn.impl.repo.PolicyXML.PolicyObject;
import org.ccnx.ccn.impl.repo.RepositoryInfo.RepositoryInfoObject;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.io.content.ContentDecodingException;
import org.ccnx.ccn.io.content.ContentNotReadyException;
import org.ccnx.ccn.profiles.nameenum.NameEnumerationResponse;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.Interest;
import org.ccnx.ccn.protocol.MalformedContentNameStringException;
/**
* Provide the generic policy-handling features of a RepositoryStore to simplify
* implementation of subclasses for different storage systems.
*/
public abstract class RepositoryStoreBase implements RepositoryStore {
protected Policy _policy = null;
protected RepositoryInfo _info = null;
protected CCNHandle _handle = null;
protected KeyManager _km = null;
/**
* Handle diagnostic requests
*
* @return true if request recognized and carried out
*/
public boolean diagnostic(String name) {
return false;
}
public abstract ContentObject getContent(Interest interest) throws RepositoryException;
public abstract NameEnumerationResponse getNamesWithPrefix(Interest i, ContentName responseName);
/**
* @return returns null prior to calls to initialize()
*/
public CCNHandle getHandle() { return _handle; }
public KeyManager getKeyManager() { return _km; }
/**
* Gets the currently valid namespace for this repository
* @return the namespace as an ArrayList of ContentNames containing prefixes of valid namespaces
*/
public ArrayList<ContentName> getNamespace() {
return _policy.getNamespace();
}
/**
* Gets the current policy for this repository
*/
public Policy getPolicy() {
return _policy;
}
/**
* Returns the current version of the repository instance.
* Subclasses must implement this method to report their version for returning
* repository information.
* @return the version as a String
*/
public abstract String getVersion();
/**
* Gets current repository information to be used as content in a ContentObject
* @param names intended for nonimplemented repository ACK protocol - currently unused
*/
public RepositoryInfoObject getRepoInfo(ContentName name, String info, ArrayList<ContentName> names) {
try {
RepositoryInfo rri = _info;
if (names != null || info != null) {
if (names != null)
rri = new RepositoryInfo(getVersion(), _info.getGlobalPrefix(), _info.getLocalName(), names);
else
rri = new RepositoryInfo(getVersion(), _info.getGlobalPrefix(), _info.getLocalName(), info);
}
RepositoryInfoObject rio = new RepositoryInfoObject(name, rri, SaveType.RAW, _handle);
rio.setFreshnessSeconds(12); // Same time as repo will express interest
return rio;
} catch (Exception e) {
Log.logStackTrace(Level.WARNING, e);
e.printStackTrace();
}
return null;
}
/**
* Initialize a repository
*/
public abstract void initialize(String repositoryRoot,
File policyFile, String localName, String globalPrefix,
String nameSpace, CCNHandle handle)
throws RepositoryException;
/**
* Initialize internal policy state, from file if policyFile != null
* This method is intended to be called at the beginning of a subclass initialize()
* method to handle the generic policy setup, after which the subclass initialize()
* should adjust policy (including calling readPolicy) as appropriate.
* If both "policy file" and "initial namespace" are non-null the policy file takes precedence
* @param policyFile policy file
* @param initial namespace
* @throws RepositoryException
* @throws FileNotFoundException
* @throws ContentDecodingException
* @throws MalformedContentNameStringException
*/
public PolicyXML startInitPolicy(File policyFile, String nameSpace) throws RepositoryException {
BasicPolicy policy = new BasicPolicy(null);
policy.setVersion(getVersion());
if (null != policyFile) {
try {
FileInputStream fis = new FileInputStream(policyFile);
try {
policy.updateFromInputStream(fis);
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
throw new RepositoryException(e.getMessage());
}
} else if (null != nameSpace) { // Try setting an initial namespace from the namespace parameter
ArrayList<ContentName> nameSpaceAL = new ArrayList<ContentName>(1);
try {
nameSpaceAL.add(ContentName.fromNative(nameSpace));
} catch (MalformedContentNameStringException e) {
Log.warning(Log.FAC_REPO, "Invalid namespace specified: {0}", nameSpace);
}
policy.setNamespace(nameSpaceAL);
}
return policy.getPolicyXML();
}
/**
* Read policy from persistent storage under standard naming convention.
* This method may be called optionally during initialization by a subclass
* after it is initialized enough to process getContent() calls
* @param globalPrefix - used to find our policy file
* @return XML for the current policy or null if no current policy
* @throws MalformedContentNameStringException
* @throws IOException
*/
public PolicyXML readPolicy(ContentName globalPrefix) throws MalformedContentNameStringException, IOException {
if (Log.isLoggable(Log.FAC_REPO, Level.INFO))
Log.info(Log.FAC_REPO, "REPO: reading policy from network: {0}/{1}/{2}", REPO_NAMESPACE, globalPrefix, REPO_POLICY);
ContentName policyName = BasicPolicy.getPolicyName(globalPrefix);
// We can't use the regular repo handle for this because we need ccnd to communicate across the faces
CCNHandle readHandle;
readHandle = CCNHandle.open(_km);
PolicyObject policyObject = new PolicyObject(policyName, readHandle);
try {
return policyObject.policyInfo();
} catch (ContentNotReadyException cge) {}
finally {readHandle.close();}
return null;
}
/**
* Complete policy initialization, to be called after subclass has adjusted
* policy state based on persistent stored records.
* @throws MalformedContentNameStringException
*/
public void finishInitPolicy(String globalPrefix, String localName) throws MalformedContentNameStringException {
_info = new RepositoryInfo(getVersion(), globalPrefix, localName);
}
public abstract NameEnumerationResponse saveContent(ContentObject content) throws RepositoryException;
public void setPolicy(Policy policy) {
_policy = policy;
}
public ContentName getGlobalPrefix() {
return _policy.getGlobalPrefix();
}
public String getLocalName() {
return _policy.getLocalName();
}
public void shutDown() {
Log.info(Log.FAC_REPO, "RespositoryStoreBase.shutdown()");
if( null != _handle )
_handle.close();
}
}