package org.wyona.yarep.impl.repo.jcr;
import org.wyona.yarep.core.Node;
import org.wyona.yarep.core.NoSuchNodeException;
import org.wyona.yarep.core.Path;
import org.wyona.yarep.core.Repository;
import org.wyona.yarep.core.RepositoryException;
import org.wyona.yarep.core.UID;
import org.wyona.commons.io.FileUtil;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import javax.jcr.Item;
import javax.jcr.PathNotFoundException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import org.apache.jackrabbit.core.TransientRepository;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
/**
* JCR based repository.
*/
public class JCRRepository implements Repository {
private static Logger log = LogManager.getLogger(JCRRepository.class);
private String repoId;
private String repoName;
private String jcrRepoDesc;
private File yarepConfigFile;
private File jackrabbitConfigFile;
private javax.jcr.Session session;
/**
*
*/
public JCRRepository() {
log.info("Initiate new Yarep-JCR repo ...");
}
/**
*
*/
public void move(String srcPath, String destPath) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public void copy(String srcPath, String destPath) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public Node getRootNode() throws RepositoryException {
try {
return new JCRNode(session.getRootNode(), session);
} catch (Exception e) {
throw new RepositoryException(e.getMessage(), e);
}
}
/**
* @param path Absolute path
*/
public boolean existsNode(String path) throws RepositoryException {
try {
if (session != null) {
Item item = this.session.getItem(path);
if (item.isNode()) {
return true;
}
} else {
throw new RepositoryException("No repository session!");
}
throw new RepositoryException("No such path exception: " + path);
} catch (PathNotFoundException e) {
log.warn("Path not found: " + path);
return false;
} catch (Exception e) {
throw new RepositoryException(e);
}
}
/**
*
*/
public Node getNodeByUUID(String uuid) throws NoSuchNodeException, RepositoryException {
log.error("Not implemented yet!");
return null;
}
/**
*
*/
public Node getNode(String path) throws NoSuchNodeException, RepositoryException {
if (log.isDebugEnabled()) log.debug("Path: " + path);
try {
Item item = this.session.getItem(path);
if (item.isNode()) {
return new JCRNode((javax.jcr.Node)item, session);
}
throw new NoSuchNodeException("not a node: " + path);
} catch (PathNotFoundException e) {
throw new NoSuchNodeException(e.getMessage(), e);
} catch (javax.jcr.RepositoryException e) {
throw new RepositoryException(e.getMessage(), e);
}
}
/**
*
*/
public void addSymbolicLink(Path target, Path link) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public String[] getRevisions(Path path) throws RepositoryException {
log.error("Not implemented yet!");
return null;
}
/**
*
*/
public UID getUID(Path path) throws RepositoryException {
log.error("Not implemented yet!");
return null;
}
/**
*
*/
public Path[] getChildren(Path path) throws RepositoryException {
log.error("Not implemented yet!");
return null;
}
/**
*
*/
public boolean exists(Path path) throws RepositoryException {
return existsNode(path.toString());
}
/**
*
*/
public boolean isCollection(Path path) throws RepositoryException {
return getNode(path.toString()).isCollection();
}
/**
*
*/
public boolean isResource(Path path) throws RepositoryException {
return getNode(path.toString()).isResource();
}
/**
*
*/
public void getURI(Path path) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public void getContentLength(Path path) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public void getValidity(Path path) throws RepositoryException {
log.error("Not implemented yet!");
}
/**
*
*/
public boolean delete(Path path) throws RepositoryException {
getNode(path.toString()).delete();
return true;
}
/**
*
*/
public boolean delete(Path path, boolean recursive) throws RepositoryException {
if (recursive) throw new RepositoryException("Not implemented yet!");
return delete(path);
}
/**
*
*/
public long getSize(Path path) throws RepositoryException {
return getNode(path.toString()).getSize();
}
/**
*
*/
public long getLastModified(Path path) throws RepositoryException {
return getNode(path.toString()).getLastModified();
}
/**
*
*/
public InputStream getInputStream(Path path) throws RepositoryException {
return getNode(path.toString()).getInputStream();
}
/**
*
*/
public OutputStream getOutputStream(Path path) throws RepositoryException {
return getNode(path.toString()).getOutputStream();
}
/**
*
*/
public Reader getReader(Path path) throws RepositoryException {
try {
return new InputStreamReader(getNode(path.toString()).getInputStream(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RepositoryException(e.getMessage(), e);
}
}
/**
*
*/
public Writer getWriter(Path path) throws RepositoryException {
try {
return new OutputStreamWriter(getNode(path.toString()).getOutputStream(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RepositoryException(e.getMessage(), e);
}
}
/**
*
*/
public File getConfigFile() {
return yarepConfigFile;
}
/**
*
*/
public String getName() {
return repoName + " (" + jcrRepoDesc + ")";
}
/**
* Like an init() method ...
*/
public void readConfiguration(File configFile) throws RepositoryException {
yarepConfigFile = configFile;
DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
Configuration config;
try {
config = builder.buildFromFile(yarepConfigFile);
// Read repo name
repoName = config.getChild("name", false).getValue();
// Read jackrabbit config file
jackrabbitConfigFile = new File(config.getChild("jackrabbit-repository-config", false).getAttribute("src"));
if (!jackrabbitConfigFile.isAbsolute()) {
jackrabbitConfigFile = FileUtil.file(yarepConfigFile.getParent(), jackrabbitConfigFile.toString());
}
if (log.isDebugEnabled()) log.debug("Jackrabbit config: " + jackrabbitConfigFile);
System.setProperty("org.apache.jackrabbit.repository.conf", jackrabbitConfigFile.toString());
System.setProperty("org.apache.jackrabbit.repository.home", jackrabbitConfigFile.getParent());
} catch (Exception e) {
log.error(e, e);
throw new RepositoryException("Could not read repository configuration: " + e.getMessage(), e);
}
try {
javax.jcr.Repository repository = new TransientRepository();
// Anonymous Login (read-only)
//session = repository.login();
// Dummy Login with write access
session = repository.login(new javax.jcr.SimpleCredentials("hugo", "password".toCharArray()));
try {
String user = session.getUserID();
jcrRepoDesc = repository.getDescriptor(javax.jcr.Repository.REP_NAME_DESC);
log.warn("Logged in as hardcoded user " + user + " to a " + jcrRepoDesc + " repository.");
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
// TODO/TBD: How can we close the session!? See close() and finalize() ...
//session.logout();
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
*
*/
protected void finalize() throws Throwable {
//super.finalize(); //not necessary if extending Object.
close();
}
/**
*
*/
public void close() throws RepositoryException {
log.warn("The JCR session will be closed ...");
session.logout();
log.warn("The JCR session has been closed.");
}
/**
*
*/
public String getID() {
return repoId;
}
/**
*
*/
public void setID(String id) {
repoId = id;
}
/**
*
*/
public String toString() {
return "JCR Wrapper Repository: ID = " + getID();
//session.exportDocumentView("/", System.out, true, false);
}
/**
* @see org.wyona.yarep.core.Repository#search(String)
*/
public Node[] search(String query) throws RepositoryException {
log.error("Implementation not finished yet!");
try {
QueryManager qm = session.getWorkspace().getQueryManager();
String[] qLang = qm.getSupportedQueryLanguages();
for (int i = 0; i < qLang.length; i++) {
if (qLang[i].equals(Query.XPATH)) {
log.error("DEBUG: Repository supports XPath ("+Query.XPATH+") queries!");
Query q = qm.createQuery("//jcr:content[jcr:contains(., '" + query + "')]", Query.XPATH);
log.error("DEBUG: Query: " + q.getStatement());
QueryResult qr = q.execute();
javax.jcr.NodeIterator ni = qr.getNodes();
java.util.Vector tmp = new java.util.Vector();
while (ni.hasNext()) {
tmp.addElement(new JCRNode(((javax.jcr.Node) ni.next()).getParent(), session));
}
log.error("DEBUG: Result size: " + tmp.size());
Node[] resultNodes = new Node[tmp.size()];
for (int j = 0; j < resultNodes.length; j++) {
resultNodes[j] = (Node) tmp.elementAt(j);
}
return resultNodes;
/*
String[] qn = qr.getColumnNames();
log.error("Column Names Length: " + qn.length);
for (int k = 0; k < qn.length; k++) {
log.error("DEBUG: Column Name: " + qn[k]);
}
*/
/*
Query aq = qm.createQuery("//*[@my-message]", Query.XPATH);
//Query aq = qm.createQuery("//*[@my-message = 'Hello Hugo']", Query.XPATH);
log.error("DEBUG: Query: " + aq.getStatement());
QueryResult aqr = aq.execute();
javax.jcr.NodeIterator ani = aqr.getNodes();
while (ani.hasNext()) {
log.error("DEBUG: Node: " + new JCRNode((javax.jcr.Node) ani.next(), session).getPath());
}
*/
} else if (qLang[i].equals(Query.SQL)) {
log.error("DEBUG: Repository supports SQL queries!");
} else {
log.error("DEBUG: Repository supports " + qLang[i] + " queries!");
}
}
} catch (Exception e) {
throw new RepositoryException(e);
}
return new Node[0];
}
/**
* @see org.wyona.yarep.core.Repository#searchProperty(String, String, String)
*/
public Node[] searchProperty(String pName, String query, String path) throws RepositoryException {
throw new RepositoryException("Not implemented yet!");
}
/**
* TODO: not implemented yet.
*/
public org.wyona.yarep.core.search.Indexer getIndexer() {
log.warn("TODO: not implemented yet.");
return null;
}
/**
* TODO: not implemented yet.
*/
public org.wyona.yarep.core.search.Searcher getSearcher() {
log.warn("TODO: not implemented yet.");
return null;
}
/**
* @see org.wyona.yarep.core.Repository#importNode(String, String, Repository)
*/
public boolean importNode(String destPath, String srcPath, Repository srcRepository) throws RepositoryException {
if (existsNode(destPath)) {
log.warn("Node '" + destPath + "' already exists within destination repository and will be overwritten!");
}
Node srcNode = srcRepository.getNode(srcPath);
if (srcNode.isCollection()) {
log.warn("This seems to be a collection and hence no data will be imported: " + srcNode.getPath());
Node destNode = org.wyona.yarep.util.YarepUtil.addNodes(this, destPath, org.wyona.yarep.core.NodeType.COLLECTION);
// TODO: What about properties?!
return true;
}
Node destNode = org.wyona.yarep.util.YarepUtil.addNodes(this, destPath, org.wyona.yarep.core.NodeType.RESOURCE);
try {
OutputStream os = destNode.getOutputStream();
org.apache.commons.io.IOUtils.copy(srcNode.getInputStream(), os);
os.close();
} catch(Exception e) {
log.error(e, e);
throw new RepositoryException(e);
}
log.warn("TODO: Implementation not finished yet!");
return false;
}
}