/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr;
import org.apache.jackrabbit.test.RepositoryStub;
import org.apache.jackrabbit.test.RepositoryStubException;
import org.exoplatform.container.StandaloneContainer;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Properties;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
/**
* Implements the <code>RepositoryStub</code> for the JCR Reference Implementation.
*/
public class ExoRepositoryStub extends RepositoryStub
{
/**
* Property for the repository name (used for jndi lookup)
*/
public static final String PROP_REPOSITORY_NAME = "org.apache.jackrabbit.repository.name";
/**
* Property for the repository configuration file (used for repository instantiation)
*/
public static final String PROP_REPOSITORY_CONFIG = "org.apache.jackrabbit.repository.config";
/**
* Property for the repository home directory (used for repository instantiation)
*/
public static final String PROP_REPOSITORY_HOME = "org.apache.jackrabbit.repository.home";
/**
* Property for the jaas config path. If the system property
* <code>java.security.auth.login.config</code> is not set this repository stub will try to read
* this property from the environment and use the value retrieved as the value for the system
* property.
*/
public static final String PROP_JAAS_CONFIG = "org.apache.jackrabbit.repository.jaas.config";
/**
* The name of the jaas config system property.
*/
private static final String SYS_JAAS_CONFIG = "java.security.auth.login.config";
/**
* The encoding of the test resources.
*/
private static final String ENCODING = "UTF-8";
/**
* The repository instance
*/
private ManageableRepository repository;
private static boolean shoutDown;
/**
* Constructor as required by the JCR TCK.
*
* @param env
* environment properties.
*/
public ExoRepositoryStub(Properties env)
{
super(env);
// set some attributes on the sessions
superuser.setAttribute("exo", "exo");
readwrite.setAttribute("exo", "exo");
readonly.setAttribute("exo", "exo");
}
public synchronized Repository getRepository() throws RepositoryStubException
{
// System.out.println("GET REP >>>>>>>>>>>>>>>>>> >>> "+repository);
if (repository == null)
{
try
{
String containerConf =
ExoRepositoryStub.class.getResource(System.getProperty("jcr.test.configuration.file")).toString();
String loginConf = ExoRepositoryStub.class.getResource("/login.conf").toString();
StandaloneContainer.addConfigurationURL(containerConf);
final StandaloneContainer servicesManager = StandaloneContainer.getInstance();
if (System.getProperty("java.security.auth.login.config") == null)
System.setProperty("java.security.auth.login.config", loginConf);
RepositoryService repositoryService =
(RepositoryService)servicesManager.getComponentInstanceOfType(RepositoryService.class);
repository = repositoryService.getRepository("db1tck");
SessionImpl session = (SessionImpl)repository.login(superuser);
try
{
prepareTestContent(session);
}
finally
{
session.logout();
}
/*
* try { repository.getNamespaceRegistry().getURI("test"); } catch (NamespaceException e) {
* repository.getNamespaceRegistry().registerNamespace("test",
* "http://www.apache.org/jackrabbit/test"); } ExtendedNodeTypeManager ntManager =
* repository.getNodeTypeManager(); InputStream inXml = ExoRepositoryStub.class
* .getResourceAsStream("/test/nodetypes-tck.xml"); ntManager.registerAllNodeTypes(inXml,
* ExtendedNodeTypeManager.IGNORE_IF_EXISTS);
*/
if (!shoutDown)
{
shoutDown = true;
}
}
catch (Exception ex)
{
ex.printStackTrace();
throw new RepositoryStubException(ex.getMessage());
}
}
return repository;
}
private void prepareTestContent(SessionImpl session) throws RepositoryException, IOException
{
// JackrabbitWorkspace workspace = (JackrabbitWorkspace)session.getWorkspace();
// Set workspaces = new HashSet(Arrays.asList(workspace.getAccessibleWorkspaceNames()));
// if (!workspaces.contains("test"))
// {
// workspace.createWorkspace("test");
// }
InternalQName testVersioable = session.getLocationFactory().parseJCRName("test:versionable").getInternalName();
NodeTypeDataManager ntHolder = session.getWorkspace().getNodeTypesHolder();
if (ntHolder.getNodeType(testVersioable) == null)
{
InputStream xml = getResource("test-nodetypes.xml");
try
{
ntHolder.registerNodeTypes(xml, ExtendedNodeTypeManager.FAIL_IF_EXISTS, NodeTypeDataManager.TEXT_XML);
}
finally
{
xml.close();
}
}
if (!session.getRootNode().hasNode("testdata"))
{
Node data = getOrAddNode(session.getRootNode(), "testdata");
addPropertyTestData(getOrAddNode(data, "property"));
addQueryTestData(getOrAddNode(data, "query"));
addNodeTestData(getOrAddNode(data, "node"));
addExportTestData(getOrAddNode(data, "docViewTest"));
session.save();
}
}
private Node getOrAddNode(Node node, String name) throws RepositoryException
{
try
{
return node.getNode(name);
}
catch (PathNotFoundException e)
{
return node.addNode(name);
}
}
/**
* Creates a boolean, double, long, calendar and a path property at the
* given node.
*/
private void addPropertyTestData(Node node) throws RepositoryException
{
node.setProperty("boolean", true);
node.setProperty("double", Math.PI);
node.setProperty("long", 90834953485278298l);
Calendar c = Calendar.getInstance();
c.set(2005, 6, 18, 17, 30);
node.setProperty("calendar", c);
ValueFactory factory = node.getSession().getValueFactory();
node.setProperty("path", factory.createValue("/", PropertyType.PATH));
node.setProperty("multi", new String[]{"one", "two", "three"});
}
/**
* Creates four nodes under the given node. Each node has a String
* property named "prop1" with some content set.
*/
private void addQueryTestData(Node node) throws RepositoryException
{
while (node.hasNode("node1"))
{
node.getNode("node1").remove();
}
getOrAddNode(node, "node1").setProperty("prop1", "You can have it good, cheap, or fast. Any two.");
getOrAddNode(node, "node1").setProperty("prop1", "foo bar");
getOrAddNode(node, "node1").setProperty("prop1", "Hello world!");
getOrAddNode(node, "node2").setProperty("prop1", "Apache Jackrabbit");
}
/**
* Creates three nodes under the given node: one of type nt:resource
* and the other nodes referencing it.
*/
private void addNodeTestData(Node node) throws RepositoryException, IOException
{
if (node.hasNode("multiReference"))
{
node.getNode("multiReference").remove();
}
if (node.hasNode("resReference"))
{
node.getNode("resReference").remove();
}
if (node.hasNode("myResource"))
{
node.getNode("myResource").remove();
}
Node resource = node.addNode("myResource", "nt:resource");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:mimeType", "text/plain");
resource.setProperty("jcr:data", new ByteArrayInputStream("Hello w\u00F6rld.".getBytes(ENCODING)));
resource.setProperty("jcr:lastModified", Calendar.getInstance());
Node resReference = getOrAddNode(node, "reference");
resReference.setProperty("ref", resource);
// make this node itself referenceable
resReference.addMixin("mix:referenceable");
Node multiReference = node.addNode("multiReference");
ValueFactory factory = node.getSession().getValueFactory();
multiReference.setProperty("ref", new Value[]{factory.createValue(resource), factory.createValue(resReference)});
}
private void addExportTestData(Node node) throws RepositoryException, IOException
{
getOrAddNode(node, "invalidXmlName").setProperty("propName", "some text");
// three nodes which should be serialized as xml text in docView export
// separated with spaces
getOrAddNode(node, "jcr:xmltext").setProperty("jcr:xmlcharacters", "A text without any special character.");
getOrAddNode(node, "some-element");
getOrAddNode(node, "jcr:xmltext").setProperty("jcr:xmlcharacters",
" The entity reference characters: <, ', ,&, >, \" should" + " be escaped in xml export. ");
getOrAddNode(node, "some-element");
getOrAddNode(node, "jcr:xmltext").setProperty("jcr:xmlcharacters", "A text without any special character.");
Node big = getOrAddNode(node, "bigNode");
big.setProperty("propName0", "SGVsbG8gd8O2cmxkLg==;SGVsbG8gd8O2cmxkLg==".split(";"), PropertyType.BINARY);
big.setProperty("propName1", "text 1");
big.setProperty("propName2", "multival text 1;multival text 2;multival text 3".split(";"));
big.setProperty("propName3", "text 1");
addExportValues(node, "propName");
addExportValues(node, "Prop<>prop");
}
/**
* create nodes with following properties
* binary & single
* binary & multival
* notbinary & single
* notbinary & multival
*/
private void addExportValues(Node node, String name) throws RepositoryException, IOException
{
String prefix = "valid";
if (name.indexOf('<') != -1)
{
prefix = "invalid";
}
node = getOrAddNode(node, prefix + "Names");
String[] texts = new String[]{"multival text 1", "multival text 2", "multival text 3"};
getOrAddNode(node, prefix + "MultiNoBin").setProperty(name, texts);
Node resource = getOrAddNode(node, prefix + "MultiBin");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:mimeType", "text/plain");
String[] values = new String[]{"SGVsbG8gd8O2cmxkLg==", "SGVsbG8gd8O2cmxkLg=="};
resource.setProperty(name, values, PropertyType.BINARY);
resource.setProperty("jcr:lastModified", Calendar.getInstance());
getOrAddNode(node, prefix + "NoBin").setProperty(name, "text 1");
resource = getOrAddNode(node, "invalidBin");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:mimeType", "text/plain");
byte[] bytes = "Hello w\u00F6rld.".getBytes(ENCODING);
resource.setProperty(name, new ByteArrayInputStream(bytes));
resource.setProperty("jcr:lastModified", Calendar.getInstance());
}
private static InputStream getResource(String name)
{
return ExoRepositoryStub.class.getResourceAsStream(name);
}
}