org.argeo.node.repo.jackrabbit,\
org.argeo.security.dao.os,\
org.argeo.security.equinox,\
+org.argeo.dep.osgi.catalina.start,\
+org.springframework.osgi.web.extender,\
+org.argeo.jackrabbit.webapp,\
#org.argeo.security.ui.initialPerspective=org.argeo.osgi.ui.explorer.perspective
#org.argeo.security.ui.initialPerspective==org.argeo.security.ui.userHomePerspective
argeo.osgi.start=\
org.springframework.osgi.extender,\
org.argeo.node.repofactory.jackrabbit,\
-org.argeo.node.repo.jackrabbit,\
org.argeo.security.dao.jackrabbit,\
org.argeo.security.equinox,\
-org.argeo.security.ui.initialPerspective=org.argeo.osgi.ui.explorer.perspective
-
+#org.argeo.security.ui.initialPerspective=org.argeo.osgi.ui.explorer.perspective
argeo.node.repo.uri=http://localhost:7070/org.argeo.jcr.webapp/remoting/node
log4j.configuration=file:../../log4j.properties
<!-- Authentication providers -->
<bean id="remoteJcrAuthenticationProvider" class="org.argeo.security.jcr.RemoteJcrAuthenticationProvider">
<property name="repositoryFactory" ref="repositoryFactory" />
+ <property name="bundleContext" ref="bundleContext" />
</bean>
<bean id="authByAdapterProvider"
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
- <bean id="argeoDataModel" class="org.argeo.jackrabbit.JackrabbitContainer"
+ <bean id="argeoDataModel" class="org.argeo.jackrabbit.JackrabbitWrapper"
init-method="init" destroy-method="destroy">
<description><![CDATA[Make sure that Argeo base data model is registered]]></description>
<property name="cndFiles">
</property>
</bean>
- <bean id="argeoDataModel" class="org.argeo.jackrabbit.JackrabbitContainer"
+ <bean id="argeoDataModel" class="org.argeo.jackrabbit.JackrabbitWrapper"
init-method="init" destroy-method="destroy">
<description><![CDATA[Make sure that Argeo base data model is registered]]></description>
<property name="cndFiles">
NameCallback nameCallback = new NameCallback("User");
PasswordCallback passwordCallback = new PasswordCallback(
"Password", false);
- final String defaultNodeUrl = "http://localhost:7070/org.argeo.jcr.webapp/remoting/node";
- final String defaultSecurityWorkspace = "security";
+ final String defaultNodeUrl = System.getProperty(NODE_REPO_URI,
+ "http://localhost:7070/org.argeo.jcr.webapp/remoting/node");
NameCallback urlCallback = new NameCallback("Site URL",
defaultNodeUrl);
- NameCallback securityWorkspaceCallback = new NameCallback(
- "Security Workspace", defaultSecurityWorkspace);
// handle callbacks
if (remote)
callbackHandler.handle(new Callback[] { nameCallback,
- passwordCallback, urlCallback,
- securityWorkspaceCallback });
+ passwordCallback, urlCallback });
else
callbackHandler.handle(new Callback[] { nameCallback,
passwordCallback });
NodeAuthenticationToken credentials;
if (remote) {
String url = urlCallback.getName();
- String workspace = securityWorkspaceCallback.getName();
credentials = new NodeAuthenticationToken(username, password,
- url, workspace);
+ url);
} else {
credentials = new NodeAuthenticationToken(username, password);
}
label.setText(callback.getPrompt());
final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
| SWT.BORDER);
+ if (callback.getDefaultName() != null) {
+ // set default value, if provided
+ text.setText(callback.getDefaultName());
+ callback.setName(callback.getDefaultName());
+ }
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
text.addModifyListener(new ModifyListener() {
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.commons.security</groupId>
<groupId>org.argeo.tp</groupId>
<artifactId>org.springframework.transaction</artifactId>
</dependency>
+
+ <!-- OSGi -->
+ <dependency>
+ <groupId>org.argeo.tp</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
<!-- Logging -->
<dependency>
<groupId>org.argeo.tp</groupId>
UsernamePasswordAuthenticationToken {
private static final long serialVersionUID = 1955222132884795213L;
private final String url;
- private final String securityWorkspace;
/** Non authenticated local constructor */
public NodeAuthenticationToken(Object principal, Object credentials) {
super(principal, credentials);
this.url = null;
- this.securityWorkspace = null;
}
/** Non authenticated remote constructor */
public NodeAuthenticationToken(Object principal, Object credentials,
- String url, String workspace) {
+ String url) {
super(principal, credentials);
this.url = url;
- this.securityWorkspace = workspace;
}
/** Authenticated constructor */
GrantedAuthority[] authorities) {
super(sat.getPrincipal(), sat.getCredentials(), authorities);
this.url = sat.getUrl();
- this.securityWorkspace = sat.getSecurityWorkspace();
}
public String getUrl() {
return url;
}
- public String getSecurityWorkspace() {
- return securityWorkspace;
- }
-
public Boolean isRemote() {
return url != null;
}
package org.argeo.security.jcr;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import java.util.Properties;
-import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.UserJcrUtils;
import org.argeo.security.NodeAuthenticationToken;
+import org.osgi.framework.BundleContext;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
public class RemoteJcrAuthenticationProvider implements AuthenticationProvider,
ArgeoNames {
private RepositoryFactory repositoryFactory;
+ private BundleContext bundleContext;
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
NodeAuthenticationToken siteAuth = (NodeAuthenticationToken) authentication;
String url = siteAuth.getUrl();
- if (url == null)
- return null;
+ if (url == null)// TODO? login on own node
+ throw new ArgeoException("No url set in " + siteAuth);
Session session;
- Node userProfile;
+ Node userProfile;
try {
SimpleCredentials sp = new SimpleCredentials(siteAuth.getName(),
siteAuth.getCredentials().toString().toCharArray());
// get repository
- Repository repository = getRepository(url, sp);
- if (repository == null)
- return null;
+ Repository repository = new RemoteJcrRepositoryWrapper(
+ repositoryFactory, url, sp);
+ if (bundleContext != null) {
+ Properties serviceProperties = new Properties();
+ serviceProperties.setProperty(
+ ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
+ ArgeoJcrConstants.ALIAS_NODE);
+ serviceProperties.setProperty(
+ ArgeoJcrConstants.JCR_REPOSITORY_URI, url);
+ bundleContext.registerService(Repository.class.getName(),
+ repository, serviceProperties);
+ }
+ // Repository repository = ArgeoJcrUtils.getRepositoryByUri(
+ // repositoryFactory, url);
+ // if (repository == null)
+ // throw new ArgeoException("Cannot connect to " + url);
- String workspace = siteAuth.getSecurityWorkspace();
- session = repository.login(sp, workspace);
- Node userHome = UserJcrUtils.getUserHome(session);
- if (userHome == null || !userHome.hasNode(ArgeoNames.ARGEO_PROFILE))
- throw new ArgeoException("No profile for user "
- + siteAuth.getName() + " in security workspace "
- + siteAuth.getSecurityWorkspace() + " of "
- + siteAuth.getUrl());
- userProfile = userHome.getNode(ArgeoNames.ARGEO_PROFILE);
+ session = repository.login(sp, null);
+
+ userProfile = UserJcrUtils.getUserProfile(session, sp.getUserID());
+ JcrUserDetails.checkAccountStatus(userProfile);
+
+ // Node userHome = UserJcrUtils.getUserHome(session);
+ // if (userHome == null ||
+ // !userHome.hasNode(ArgeoNames.ARGEO_PROFILE))
+ // throw new ArgeoException("No profile for user "
+ // + siteAuth.getName() + " in security workspace "
+ // + siteAuth.getSecurityWorkspace() + " of "
+ // + siteAuth.getUrl());
+ // userProfile = userHome.getNode(ArgeoNames.ARGEO_PROFILE);
} catch (RepositoryException e) {
throw new BadCredentialsException(
"Cannot authenticate " + siteAuth, e);
}
try {
- JcrUserDetails.checkAccountStatus(userProfile);
+ Node userHome = UserJcrUtils.getUserHome(session);
// retrieve remote roles
List<GrantedAuthority> authoritiesList = new ArrayList<GrantedAuthority>();
- if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
- Value[] roles = userProfile.getProperty(
+ if (userHome != null
+ && userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+ Value[] roles = userHome.getProperty(
ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
for (int i = 0; i < roles.length; i++)
authoritiesList.add(new GrantedAuthorityImpl(roles[i]
}
}
- protected Repository getRepository(String url, Credentials credentials)
- throws RepositoryException {
- Map<String, String> parameters = new HashMap<String, String>();
- parameters.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, url);
- return repositoryFactory.getRepository(parameters);
- }
-
@SuppressWarnings("rawtypes")
public boolean supports(Class authentication) {
return NodeAuthenticationToken.class.isAssignableFrom(authentication);
this.repositoryFactory = repositoryFactory;
}
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Mathieu Baudier
+ *
+ * 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 org.argeo.security.jcr;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrUtils;
+import org.argeo.jcr.JcrRepositoryWrapper;
+import org.argeo.security.NodeAuthenticationToken;
+import org.argeo.security.SystemAuthentication;
+import org.springframework.security.Authentication;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
+
+/**
+ * Wrapper around a remote Jackrabbit repository which allows to simplify
+ * configuration and intercept some actions. It exposes itself as a
+ * {@link Repository}.
+ */
+public class RemoteJcrRepositoryWrapper extends JcrRepositoryWrapper {
+ private final static Log log = LogFactory
+ .getLog(RemoteJcrRepositoryWrapper.class);
+
+ private String uri = null;
+
+ private RepositoryFactory repositoryFactory;
+
+ // remote
+ private Credentials remoteSystemCredentials = null;
+
+ /**
+ * Empty constructor, {@link #init()} should be called after properties have
+ * been set
+ */
+ public RemoteJcrRepositoryWrapper() {
+ }
+
+ /**
+ * Embedded constructor, calling the {@link #init()} method.
+ *
+ * @param alias
+ * if not null the repository will be published under this alias
+ */
+ public RemoteJcrRepositoryWrapper(RepositoryFactory repositoryFactory,
+ String uri, Credentials remoteSystemCredentials) {
+ this.repositoryFactory = repositoryFactory;
+ this.uri = uri;
+ this.remoteSystemCredentials = remoteSystemCredentials;
+ init();
+ }
+
+ public void init() {
+ Repository repository = createJackrabbitRepository();
+ setRepository(repository);
+ }
+
+ /** Actually creates the new repository. */
+ protected Repository createJackrabbitRepository() {
+ long begin = System.currentTimeMillis();
+ try {
+ if (uri == null || uri.trim().equals(""))
+ throw new ArgeoException("Remote URI not set");
+
+ Repository repository = ArgeoJcrUtils.getRepositoryByUri(
+ repositoryFactory, uri);
+ if (repository == null)
+ throw new ArgeoException("Remote JCR repository " + uri
+ + " not found");
+ double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+ log.info("Created remote JCR repository in " + duration
+ + " s from URI " + uri);
+ // we assume that the data model of the remote repository has
+ // been properly initialized
+ return repository;
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot create remote JCR repository "
+ + uri, e);
+ }
+ }
+
+ /** Shutdown the repository */
+ public void destroy() throws Exception {
+ super.destroy();
+ }
+
+ /** Central login method */
+ public Session login(Credentials credentials, String workspaceName)
+ throws LoginException, NoSuchWorkspaceException,
+ RepositoryException {
+
+ // retrieve credentials for remote
+ if (credentials == null) {
+ Authentication authentication = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (authentication != null) {
+ if (authentication instanceof UsernamePasswordAuthenticationToken) {
+ UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication;
+ credentials = new SimpleCredentials(upat.getName(), upat
+ .getCredentials().toString().toCharArray());
+ } else if ((authentication instanceof SystemAuthentication)
+ || (authentication instanceof NodeAuthenticationToken)) {
+ credentials = remoteSystemCredentials;
+ }
+ }
+ }
+
+ return super.login(credentials, workspaceName);
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+ this.repositoryFactory = repositoryFactory;
+ }
+
+ public void setRemoteSystemCredentials(Credentials remoteSystemCredentials) {
+ this.remoteSystemCredentials = remoteSystemCredentials;
+ }
+
+}
<service ref="nodeJcrRepository" interface="javax.jcr.Repository">\r
<service-properties>\r
<beans:entry key="argeo.jcr.repository.alias" value="node" />\r
+ <beans:entry key="argeo.jcr.repository.home" value="${argeo.node.repo.home}" />\r
</service-properties>\r
</service>\r
</beans:beans>
\ No newline at end of file
<bean id="nodeJcrRepository" class="org.argeo.jackrabbit.JackrabbitContainer"
init-method="init" destroy-method="destroy">
- <property name="uri" value="${argeo.node.repo.uri}" />
<property name="homeDirectory" value="${argeo.node.repo.home}" />
<property name="configuration" value="${argeo.node.repo.configuration}" />
<property name="variables" value="osgibundle:/noderepo.properties" />
- <!-- For remote testing -->
- <property name="remoteSystemCredentials">
- <bean class="javax.jcr.SimpleCredentials">
- <constructor-arg value="${argeo.node.repo.remoteSystemUser}" />
- <constructor-arg value="${argeo.node.repo.remoteSystemPassword}" />
- </bean>
- </property>
</bean>
</beans>
\ No newline at end of file
argeo.node.repo.dbuser=sa
argeo.node.repo.dbpassword=
-## Remote
-# Remote repository URI (overrides other configurations if not empty)
-argeo.node.repo.uri=
-# may change in the near future:
-argeo.node.repo.remoteSystemUser=root
-argeo.node.repo.remoteSystemPassword=demo
-
# ADVANCED
argeo.node.repo.maxPoolSize=10
\ No newline at end of file
import javax.jcr.observation.EventListener;
import javax.jcr.observation.ObservationManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.argeo.ArgeoException;
import org.argeo.eclipse.ui.TreeParent;
import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
*/
public class GenericJcrBrowser extends AbstractJcrBrowser {
- // private final static Log log =
- // LogFactory.getLog(GenericJcrBrowser.class);
+ private final static Log log = LogFactory.getLog(GenericJcrBrowser.class);
public final static String ID = JcrExplorerPlugin.ID + ".browserView";
private boolean sortChildNodes = false;
resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
if (jcrKeyring != null)
try {
+ log.debug("userID=" + jcrKeyring.getSession().getUserID());
ObservationManager observationManager = jcrKeyring.getSession()
.getWorkspace().getObservationManager();
observationManager.addEventListener(resultsObserver,
*/
package org.argeo.jackrabbit;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
+import java.util.UUID;
-import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
-import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.api.JackrabbitRepository;
-import org.apache.jackrabbit.commons.NamespaceHelper;
-import org.apache.jackrabbit.commons.cnd.CndImporter;
import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
import org.argeo.jcr.JcrUtils;
-import org.argeo.security.SystemAuthentication;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.security.Authentication;
-import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.util.SystemPropertyUtils;
+import org.xml.sax.InputSource;
/**
* Wrapper around a Jackrabbit repository which allows to configure it in Spring
* and expose it as a {@link Repository}.
*/
-public class JackrabbitContainer extends JackrabbitWrapper implements
- ResourceLoaderAware {
+public class JackrabbitContainer extends JackrabbitWrapper {
private Log log = LogFactory.getLog(JackrabbitContainer.class);
- // remote
- private Credentials remoteSystemCredentials = null;
-
// local
private Resource configuration;
private Resource variables;
- private ResourceLoader resourceLoader;
-
- // data model
- /** Node type definitions in CND format */
- private List<String> cndFiles = new ArrayList<String>();
- /**
- * Always import CNDs. Useful during development of new data models. In
- * production, explicit migration processes should be used.
- */
- private Boolean forceCndImport = false;
+ private RepositoryConfig repositoryConfig;
+ private File homeDirectory;
+ private Boolean inMemory = false;
/** Migrations to execute (if not already done) */
private Set<JackrabbitDataModelMigration> dataModelMigrations = new HashSet<JackrabbitDataModelMigration>();
- /** Namespaces to register: key is prefix, value namespace */
- private Map<String, String> namespaces = new HashMap<String, String>();
-
- private BundleContext bundleContext;
-
/**
* Empty constructor, {@link #init()} should be called after properties have
* been set
public JackrabbitContainer() {
}
- /**
- * Convenience constructor for remote, {@link #init()} is called in the
- * constructor.
- */
- public JackrabbitContainer(String uri, Credentials remoteSystemCredentials) {
- setUri(uri);
- setRemoteSystemCredentials(remoteSystemCredentials);
- init();
- }
+ public void init() {
+ long begin = System.currentTimeMillis();
- @Override
- protected void postInitWrapped() {
- prepareDataModel();
- }
+ if (getRepository() != null)
+ throw new ArgeoException(
+ "Cannot be used to wrap another repository");
+ Repository repository = createJackrabbitRepository();
+ super.setRepository(repository);
- @Override
- protected void postInitNew() {
// migrate if needed
migrate();
// apply new CND files after migration
- if (cndFiles != null && cndFiles.size() > 0)
- prepareDataModel();
- }
-
- /*
- * DATA MODEL
- */
+ prepareDataModel();
- /**
- * Import declared node type definitions and register namespaces. Tries to
- * update the node definitions if they have changed. In case of failures an
- * error will be logged but no exception will be thrown.
- */
- protected void prepareDataModel() {
- // importing node def on remote si currently not supported
- if (isRemote())
- return;
+ double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+ if (log.isDebugEnabled())
+ log.debug("Initialized JCR repository wrapper in " + duration
+ + " s");
+ }
- Session session = null;
+ /** Actually creates the new repository. */
+ protected Repository createJackrabbitRepository() {
+ long begin = System.currentTimeMillis();
+ InputStream configurationIn = null;
+ Repository repository;
try {
- if (remoteSystemCredentials == null)
- session = login();
- else
- session = login(remoteSystemCredentials);
- // register namespaces
- if (namespaces.size() > 0) {
- NamespaceHelper namespaceHelper = new NamespaceHelper(session);
- namespaceHelper.registerNamespaces(namespaces);
+ // temporary
+ if (inMemory && getHomeDirectory().exists()) {
+ FileUtils.deleteDirectory(getHomeDirectory());
+ log.warn("Deleted Jackrabbit home directory "
+ + getHomeDirectory());
}
- // load CND files from classpath or as URL
- for (String resUrl : cndFiles) {
- boolean classpath;
- // normalize URL
- if (resUrl.startsWith("classpath:")) {
- resUrl = resUrl.substring("classpath:".length());
- classpath = true;
- } else if (resUrl.indexOf(':') < 0) {
- if (!resUrl.startsWith("/")) {
- resUrl = "/" + resUrl;
- log.warn("Classpath should start with '/'");
- }
- // resUrl = "classpath:" + resUrl;
- classpath = true;
- } else {
- classpath = false;
- }
-
- URL url;
- Bundle dataModelBundle = null;
- if (classpath) {
- if (bundleContext != null) {
- Bundle currentBundle = bundleContext.getBundle();
- url = currentBundle.getResource(resUrl);
- if (url != null) {// found
- dataModelBundle = findDataModelBundle(resUrl);
- }
- } else {
- url = getClass().getClassLoader().getResource(resUrl);
- // if (url == null)
- // url = Thread.currentThread()
- // .getContextClassLoader()
- // .getResource(resUrl);
- }
- } else {
- url = new URL(resUrl);
- }
-
- // check existing data model nodes
- new NamespaceHelper(session).registerNamespace(
- ArgeoNames.ARGEO, ArgeoNames.ARGEO_NAMESPACE);
- if (!session
- .itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH))
- JcrUtils.mkdirs(session,
- ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
- Node dataModels = session
- .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
- NodeIterator it = dataModels.getNodes();
- Node dataModel = null;
- while (it.hasNext()) {
- Node node = it.nextNode();
- if (node.getProperty(ArgeoNames.ARGEO_URI).getString()
- .equals(resUrl)) {
- dataModel = node;
- break;
- }
- }
-
- // does nothing if data model already registered
- if (dataModel != null && !forceCndImport) {
- if (dataModelBundle != null) {
- String version = dataModel.getProperty(
- ArgeoNames.ARGEO_DATA_MODEL_VERSION)
- .getString();
- String dataModelBundleVersion = dataModelBundle
- .getVersion().toString();
- if (!version.equals(dataModelBundleVersion)) {
- log.warn("Data model with version "
- + dataModelBundleVersion
- + " available, current version is "
- + version);
- }
- }
- // do not implicitly update
- return;
- }
- InputStream in = null;
- Reader reader = null;
- try {
- if (url != null) {
- in = url.openStream();
- } else if (resourceLoader != null) {
- Resource res = resourceLoader.getResource(resUrl);
- in = res.getInputStream();
- url = res.getURL();
- } else {
- throw new ArgeoException("No " + resUrl
- + " in the classpath,"
- + " make sure the containing"
- + " package is visible.");
- }
-
- reader = new InputStreamReader(in);
- // actually imports the CND
- CndImporter.registerNodeTypes(reader, session, true);
-
- // FIXME: what if argeo.cnd would not be the first called on
- // a new repo? argeo:dataModel would not be found
- String fileName = FilenameUtils.getName(url.getPath());
- if (dataModel == null) {
- dataModel = dataModels.addNode(fileName);
- dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
- dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
- } else {
- session.getWorkspace().getVersionManager()
- .checkout(dataModel.getPath());
- }
- if (dataModelBundle != null)
- dataModel.setProperty(
- ArgeoNames.ARGEO_DATA_MODEL_VERSION,
- dataModelBundle.getVersion().toString());
- else
- dataModel.setProperty(
- ArgeoNames.ARGEO_DATA_MODEL_VERSION, "0.0.0");
- JcrUtils.updateLastModified(dataModel);
- session.save();
- session.getWorkspace().getVersionManager()
- .checkin(dataModel.getPath());
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(reader);
- }
-
- if (log.isDebugEnabled())
- log.debug("Data model "
- + resUrl
- + (dataModelBundle != null ? ", version "
- + dataModelBundle.getVersion()
- + ", bundle "
- + dataModelBundle.getSymbolicName() : ""));
- }
+ // process configuration file
+ Properties vars = getConfigurationProperties();
+ configurationIn = readConfiguration();
+ vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+ getHomeDirectory().getCanonicalPath());
+ repositoryConfig = RepositoryConfig.create(new InputSource(
+ configurationIn), vars);
+
+ //
+ // Actual repository creation
+ //
+ repository = RepositoryImpl.create(repositoryConfig);
+
+ double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+ if (log.isTraceEnabled())
+ log.trace("Created Jackrabbit repository in " + duration
+ + " s, home: " + getHomeDirectory());
+
+ return repository;
} catch (Exception e) {
- JcrUtils.discardQuietly(session);
- throw new ArgeoException("Cannot import node type definitions "
- + cndFiles, e);
+ throw new ArgeoException("Cannot create Jackrabbit repository "
+ + getHomeDirectory(), e);
} finally {
- JcrUtils.logoutQuietly(session);
+ IOUtils.closeQuietly(configurationIn);
}
+ }
+
+ /** Lazy init. */
+ protected File getHomeDirectory() {
+ try {
+ if (homeDirectory == null) {
+ if (inMemory) {
+ homeDirectory = new File(
+ System.getProperty("java.io.tmpdir")
+ + File.separator
+ + System.getProperty("user.name")
+ + File.separator + "jackrabbit-"
+ + UUID.randomUUID());
+ homeDirectory.mkdirs();
+ // will it work if directory is not empty??
+ homeDirectory.deleteOnExit();
+ }
+ }
+ return homeDirectory.getCanonicalFile();
+ } catch (IOException e) {
+ throw new ArgeoException("Cannot get canonical file for "
+ + homeDirectory, e);
+ }
}
/** Executes migrations, if needed. */
protected void migrate() {
- // Remote migration not supported
- if (isRemote())
- return;
-
// No migration to perform
if (dataModelMigrations.size() == 0)
return;
}
- /*
- * REPOSITORY INTERCEPTOR
- */
- /** Central login method */
- public Session login(Credentials credentials, String workspaceName)
- throws LoginException, NoSuchWorkspaceException,
- RepositoryException {
-
- // retrieve credentials for remote
- if (credentials == null && isRemote()) {
- Authentication authentication = SecurityContextHolder.getContext()
- .getAuthentication();
- if (authentication != null) {
- if (authentication instanceof UsernamePasswordAuthenticationToken) {
- UsernamePasswordAuthenticationToken upat = (UsernamePasswordAuthenticationToken) authentication;
- credentials = new SimpleCredentials(upat.getName(), upat
- .getCredentials().toString().toCharArray());
- } else if ((authentication instanceof SystemAuthentication)
- && remoteSystemCredentials != null) {
- credentials = remoteSystemCredentials;
+ /** Shutdown the repository */
+ public void destroy() throws Exception {
+ Repository repository = getRepository();
+ if (repository != null && repository instanceof RepositoryImpl) {
+ long begin = System.currentTimeMillis();
+ ((RepositoryImpl) repository).shutdown();
+ if (inMemory)
+ if (getHomeDirectory().exists()) {
+ FileUtils.deleteDirectory(getHomeDirectory());
+ if (log.isDebugEnabled())
+ log.debug("Deleted Jackrabbit home directory "
+ + getHomeDirectory());
}
- }
+ double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+ log.info("Destroyed Jackrabbit repository in " + duration
+ + " s, home: " + getHomeDirectory());
}
-
- return super.login(credentials, workspaceName);
+ repository = null;
}
/*
* UTILITIES
*/
-
- @Override
+ /**
+ * Reads the configuration which will initialize a {@link RepositoryConfig}.
+ */
protected InputStream readConfiguration() {
try {
return configuration != null ? configuration.getInputStream()
}
}
- @Override
+ /**
+ * Reads the variables which will initialize a {@link Properties}. Returns
+ * null by default, to be overridden.
+ *
+ * @return a new stream or null if no variables available
+ */
protected InputStream readVariables() {
try {
return variables != null ? variables.getInputStream() : null;
}
}
- @Override
+ /**
+ * Resolves ${} placeholders in the provided string. Based on system
+ * properties if no map is provided.
+ */
protected String resolvePlaceholders(String string,
Map<String, String> variables) {
return SystemPropertyUtils.resolvePlaceholders(string);
}
- /** Find which OSGi bundle provided the data model resource */
- protected Bundle findDataModelBundle(String resUrl) {
- if (resUrl.startsWith("/"))
- resUrl = resUrl.substring(1);
- String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/',
- '.');
- ServiceReference paSr = bundleContext
- .getServiceReference(PackageAdmin.class.getName());
- PackageAdmin packageAdmin = (PackageAdmin) bundleContext
- .getService(paSr);
-
- // find exported package
- ExportedPackage exportedPackage = null;
- ExportedPackage[] exportedPackages = packageAdmin
- .getExportedPackages(pkg);
- if (exportedPackages == null)
- throw new ArgeoException("No exported package found for " + pkg);
- for (ExportedPackage ep : exportedPackages) {
- for (Bundle b : ep.getImportingBundles()) {
- if (b.getBundleId() == bundleContext.getBundle().getBundleId()) {
- exportedPackage = ep;
- break;
- }
+ /** Generates the properties to use in the configuration. */
+ protected Properties getConfigurationProperties() {
+ InputStream propsIn = null;
+ Properties vars;
+ try {
+ vars = new Properties();
+ propsIn = readVariables();
+ if (propsIn != null) {
+ vars.load(propsIn);
+ }
+ // resolve system properties
+ for (Object key : vars.keySet()) {
+ // TODO: implement a smarter mechanism to resolve nested ${}
+ String newValue = resolvePlaceholders(
+ vars.getProperty(key.toString()), null);
+ vars.put(key, newValue);
+ }
+ // override with system properties
+ vars.putAll(System.getProperties());
+
+ if (log.isTraceEnabled()) {
+ log.trace("Jackrabbit config variables:");
+ for (Object key : new TreeSet<Object>(vars.keySet()))
+ log.trace(key + "=" + vars.getProperty(key.toString()));
}
- }
- Bundle exportingBundle = null;
- if (exportedPackage != null) {
- exportingBundle = exportedPackage.getExportingBundle();
- } else {
- throw new ArgeoException("No OSGi exporting package found for "
- + resUrl);
+ } catch (IOException e) {
+ throw new ArgeoException("Cannot read configuration properties", e);
+ } finally {
+ IOUtils.closeQuietly(propsIn);
}
- return exportingBundle;
+ return vars;
}
/*
* FIELDS ACCESS
*/
- public void setConfiguration(Resource configuration) {
- this.configuration = configuration;
- }
-
- public void setNamespaces(Map<String, String> namespaces) {
- this.namespaces = namespaces;
- }
- public void setCndFiles(List<String> cndFiles) {
- this.cndFiles = cndFiles;
+ public void setHomeDirectory(File homeDirectory) {
+ this.homeDirectory = homeDirectory;
}
- public void setVariables(Resource variables) {
- this.variables = variables;
+ public void setInMemory(Boolean inMemory) {
+ this.inMemory = inMemory;
}
- public void setRemoteSystemCredentials(Credentials remoteSystemCredentials) {
- this.remoteSystemCredentials = remoteSystemCredentials;
+ public void setRepository(Repository repository) {
+ throw new ArgeoException("Cannot be used to wrap another repository");
}
public void setDataModelMigrations(
this.dataModelMigrations = dataModelMigrations;
}
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- public void setForceCndImport(Boolean forceCndUpdate) {
- this.forceCndImport = forceCndUpdate;
+ public void setVariables(Resource variables) {
+ this.variables = variables;
}
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
+ public void setConfiguration(Resource configuration) {
+ this.configuration = configuration;
}
}
*/
package org.argeo.jackrabbit;
-import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.Properties;
-import java.util.TreeSet;
-import java.util.UUID;
-import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.jcr.Value;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
-import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
+import org.apache.jackrabbit.commons.NamespaceHelper;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
import org.argeo.ArgeoException;
-import org.xml.sax.InputSource;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrRepositoryWrapper;
+import org.argeo.jcr.JcrUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
/**
* Wrapper around a Jackrabbit repository which allows to simplify configuration
* and intercept some actions. It exposes itself as a {@link Repository}.
*/
-public abstract class JackrabbitWrapper implements Repository {
+public class JackrabbitWrapper extends JcrRepositoryWrapper implements
+ ResourceLoaderAware {
private Log log = LogFactory.getLog(JackrabbitWrapper.class);
- // remote
- private String uri = null;
-
// local
- private RepositoryConfig repositoryConfig;
- private File homeDirectory;
- private Boolean inMemory = false;
+ private ResourceLoader resourceLoader;
+
+ // data model
+ /** Node type definitions in CND format */
+ private List<String> cndFiles = new ArrayList<String>();
+ /**
+ * Always import CNDs. Useful during development of new data models. In
+ * production, explicit migration processes should be used.
+ */
+ private Boolean forceCndImport = false;
- // wrapped repository
- private Repository repository;
+ /** Namespaces to register: key is prefix, value namespace */
+ private Map<String, String> namespaces = new HashMap<String, String>();
- private Boolean autocreateWorkspaces = false;
+ private BundleContext bundleContext;
/**
* Empty constructor, {@link #init()} should be called after properties have
public JackrabbitWrapper() {
}
- /**
- * Reads the configuration which will initialize a {@link RepositoryConfig}.
- */
- protected abstract InputStream readConfiguration();
-
- /**
- * Reads the variables which will initialize a {@link Properties}. Returns
- * null by default, to be overridden.
- *
- * @return a new stream or null if no variables available
- */
- protected InputStream readVariables() {
- return null;
- }
-
- /**
- * Resolves ${} placeholders in the provided string. Based on system
- * properties if no map is provided.
- */
- protected abstract String resolvePlaceholders(String string,
- Map<String, String> variables);
-
- /** Initializes */
+ @Override
public void init() {
- long begin = System.currentTimeMillis();
-
- if (repository != null) {
- // we are just wrapping another repository
- postInitWrapped();
- } else {
- createJackrabbitRepository();
- postInitNew();
- }
-
- double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
- if (log.isTraceEnabled())
- log.trace("Initialized Jackrabbit wrapper in " + duration + " s");
+ prepareDataModel();
}
- /**
- * Called after initialization of an already existing {@link Repository}
- * which is being wrapped (e.g. in order to impact its data model). To be
- * overridden, does nothing by default.
+ /*
+ * DATA MODEL
*/
- protected void postInitWrapped() {
-
- }
/**
- * Called after initialization of a new {@link Repository} either local or
- * remote. To be overridden, does nothing by default.
+ * Import declared node type definitions and register namespaces. Tries to
+ * update the node definitions if they have changed. In case of failures an
+ * error will be logged but no exception will be thrown.
*/
- protected void postInitNew() {
+ protected void prepareDataModel() {
+ if ((cndFiles == null || cndFiles.size() == 0)
+ && (namespaces == null || namespaces.size() == 0))
+ return;
+
+ Session session = null;
+ try {
+ session = login();
+ // register namespaces
+ if (namespaces.size() > 0) {
+ NamespaceHelper namespaceHelper = new NamespaceHelper(session);
+ namespaceHelper.registerNamespaces(namespaces);
+ }
- }
+ // load CND files from classpath or as URL
+ for (String resUrl : cndFiles) {
+ boolean classpath;
+ // normalize URL
+ if (resUrl.startsWith("classpath:")) {
+ resUrl = resUrl.substring("classpath:".length());
+ classpath = true;
+ } else if (resUrl.indexOf(':') < 0) {
+ if (!resUrl.startsWith("/")) {
+ resUrl = "/" + resUrl;
+ log.warn("Classpath should start with '/'");
+ }
+ // resUrl = "classpath:" + resUrl;
+ classpath = true;
+ } else {
+ classpath = false;
+ }
- /** Actually creates the new repository. */
- protected void createJackrabbitRepository() {
- long begin = System.currentTimeMillis();
- InputStream configurationIn = null;
- try {
- if (uri != null && !uri.trim().equals("")) {// remote
- Map<String, String> params = new HashMap<String, String>();
- params.put(
- org.apache.jackrabbit.commons.JcrUtils.REPOSITORY_URI,
- uri);
- repository = new Jcr2davRepositoryFactory()
- .getRepository(params);
- if (repository == null)
- throw new ArgeoException("Remote Davex repository " + uri
- + " not found");
- double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
- log.info("Created Jackrabbit repository in " + duration
- + " s from URI " + uri);
- // we assume that the data model of the remote repository has
- // been properly initialized
- } else {// local
- // force uri to null in order to optimize isRemote()
- uri = null;
+ URL url;
+ Bundle dataModelBundle = null;
+ if (classpath) {
+ if (bundleContext != null) {
+ Bundle currentBundle = bundleContext.getBundle();
+ url = currentBundle.getResource(resUrl);
+ if (url != null) {// found
+ dataModelBundle = findDataModelBundle(resUrl);
+ }
+ } else {
+ url = getClass().getClassLoader().getResource(resUrl);
+ // if (url == null)
+ // url = Thread.currentThread()
+ // .getContextClassLoader()
+ // .getResource(resUrl);
+ }
+ } else {
+ url = new URL(resUrl);
+ }
- // temporary
- if (inMemory && getHomeDirectory().exists()) {
- FileUtils.deleteDirectory(getHomeDirectory());
- log.warn("Deleted Jackrabbit home directory "
- + getHomeDirectory());
+ // check existing data model nodes
+ new NamespaceHelper(session).registerNamespace(
+ ArgeoNames.ARGEO, ArgeoNames.ARGEO_NAMESPACE);
+ if (!session
+ .itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH))
+ JcrUtils.mkdirs(session,
+ ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
+ Node dataModels = session
+ .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
+ NodeIterator it = dataModels.getNodes();
+ Node dataModel = null;
+ while (it.hasNext()) {
+ Node node = it.nextNode();
+ if (node.getProperty(ArgeoNames.ARGEO_URI).getString()
+ .equals(resUrl)) {
+ dataModel = node;
+ break;
+ }
}
- // process configuration file
- Properties vars = getConfigurationProperties();
- configurationIn = readConfiguration();
- vars.put(
- RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
- getHomeDirectory().getCanonicalPath());
- repositoryConfig = RepositoryConfig.create(new InputSource(
- configurationIn), vars);
+ // does nothing if data model already registered
+ if (dataModel != null && !forceCndImport) {
+ if (dataModelBundle != null) {
+ String version = dataModel.getProperty(
+ ArgeoNames.ARGEO_DATA_MODEL_VERSION)
+ .getString();
+ String dataModelBundleVersion = dataModelBundle
+ .getVersion().toString();
+ if (!version.equals(dataModelBundleVersion)) {
+ log.warn("Data model with version "
+ + dataModelBundleVersion
+ + " available, current version is "
+ + version);
+ }
+ }
+ // do not implicitly update
+ return;
+ }
- //
- // Actual repository creation
- //
- repository = RepositoryImpl.create(repositoryConfig);
+ InputStream in = null;
+ Reader reader = null;
+ try {
+ if (url != null) {
+ in = url.openStream();
+ } else if (resourceLoader != null) {
+ Resource res = resourceLoader.getResource(resUrl);
+ in = res.getInputStream();
+ url = res.getURL();
+ } else {
+ throw new ArgeoException("No " + resUrl
+ + " in the classpath,"
+ + " make sure the containing"
+ + " package is visible.");
+ }
+
+ reader = new InputStreamReader(in);
+ // actually imports the CND
+ CndImporter.registerNodeTypes(reader, session, true);
+
+ // FIXME: what if argeo.cnd would not be the first called on
+ // a new repo? argeo:dataModel would not be found
+ String fileName = FilenameUtils.getName(url.getPath());
+ if (dataModel == null) {
+ dataModel = dataModels.addNode(fileName);
+ dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
+ dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
+ } else {
+ session.getWorkspace().getVersionManager()
+ .checkout(dataModel.getPath());
+ }
+ if (dataModelBundle != null)
+ dataModel.setProperty(
+ ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+ dataModelBundle.getVersion().toString());
+ else
+ dataModel.setProperty(
+ ArgeoNames.ARGEO_DATA_MODEL_VERSION, "0.0.0");
+ JcrUtils.updateLastModified(dataModel);
+ session.save();
+ session.getWorkspace().getVersionManager()
+ .checkin(dataModel.getPath());
+ } finally {
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(reader);
+ }
- double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
- if (log.isTraceEnabled())
- log.trace("Created Jackrabbit repository in " + duration
- + " s, home: " + getHomeDirectory());
+ if (log.isDebugEnabled())
+ log.debug("Data model "
+ + resUrl
+ + (dataModelBundle != null ? ", version "
+ + dataModelBundle.getVersion()
+ + ", bundle "
+ + dataModelBundle.getSymbolicName() : ""));
}
} catch (Exception e) {
- throw new ArgeoException("Cannot create Jackrabbit repository "
- + getHomeDirectory(), e);
+ JcrUtils.discardQuietly(session);
+ throw new ArgeoException("Cannot import node type definitions "
+ + cndFiles, e);
} finally {
- IOUtils.closeQuietly(configurationIn);
- }
- }
-
- /** Lazy init. */
- protected File getHomeDirectory() {
- try {
- if (homeDirectory == null) {
- if (inMemory) {
- homeDirectory = new File(
- System.getProperty("java.io.tmpdir")
- + File.separator
- + System.getProperty("user.name")
- + File.separator + "jackrabbit-"
- + UUID.randomUUID());
- homeDirectory.mkdirs();
- // will it work if directory is not empty??
- homeDirectory.deleteOnExit();
- }
- }
-
- return homeDirectory.getCanonicalFile();
- } catch (IOException e) {
- throw new ArgeoException("Cannot get canonical file for "
- + homeDirectory, e);
+ JcrUtils.logoutQuietly(session);
}
- }
- /** Shutdown the repository */
- public void destroy() throws Exception {
- if (repository != null && repository instanceof RepositoryImpl) {
- long begin = System.currentTimeMillis();
- ((RepositoryImpl) repository).shutdown();
- if (inMemory)
- if (getHomeDirectory().exists()) {
- FileUtils.deleteDirectory(getHomeDirectory());
- if (log.isDebugEnabled())
- log.debug("Deleted Jackrabbit home directory "
- + getHomeDirectory());
- }
- double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
- log.info("Destroyed Jackrabbit repository in " + duration
- + " s, home: " + getHomeDirectory());
- }
}
- /**
- * @deprecated explicitly declare {@link #destroy()} as destroy-method
- * instead.
+ /*
+ * REPOSITORY INTERCEPTOR
*/
- public void dispose() throws Exception {
- log.error("## Declare destroy-method=\"destroy\". in the Jackrabbit container bean");
- destroy();
- }
/*
* UTILITIES
*/
-
- /** Generates the properties to use in the configuration. */
- protected Properties getConfigurationProperties() {
- InputStream propsIn = null;
- Properties vars;
- try {
- vars = new Properties();
- propsIn = readVariables();
- if (propsIn != null) {
- vars.load(propsIn);
- }
- // resolve system properties
- for (Object key : vars.keySet()) {
- // TODO: implement a smarter mechanism to resolve nested ${}
- String newValue = resolvePlaceholders(
- vars.getProperty(key.toString()), null);
- vars.put(key, newValue);
- }
- // override with system properties
- vars.putAll(System.getProperties());
-
- if (log.isTraceEnabled()) {
- log.trace("Jackrabbit config variables:");
- for (Object key : new TreeSet<Object>(vars.keySet()))
- log.trace(key + "=" + vars.getProperty(key.toString()));
+ /** Find which OSGi bundle provided the data model resource */
+ protected Bundle findDataModelBundle(String resUrl) {
+ if (resUrl.startsWith("/"))
+ resUrl = resUrl.substring(1);
+ String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/',
+ '.');
+ ServiceReference paSr = bundleContext
+ .getServiceReference(PackageAdmin.class.getName());
+ PackageAdmin packageAdmin = (PackageAdmin) bundleContext
+ .getService(paSr);
+
+ // find exported package
+ ExportedPackage exportedPackage = null;
+ ExportedPackage[] exportedPackages = packageAdmin
+ .getExportedPackages(pkg);
+ if (exportedPackages == null)
+ throw new ArgeoException("No exported package found for " + pkg);
+ for (ExportedPackage ep : exportedPackages) {
+ for (Bundle b : ep.getImportingBundles()) {
+ if (b.getBundleId() == bundleContext.getBundle().getBundleId()) {
+ exportedPackage = ep;
+ break;
+ }
}
-
- } catch (IOException e) {
- throw new ArgeoException("Cannot read configuration properties", e);
- } finally {
- IOUtils.closeQuietly(propsIn);
- }
- return vars;
- }
-
- /*
- * DELEGATED JCR REPOSITORY METHODS
- */
-
- public String getDescriptor(String key) {
- return getRepository().getDescriptor(key);
- }
-
- public String[] getDescriptorKeys() {
- return getRepository().getDescriptorKeys();
- }
-
- /** Central login method */
- public Session login(Credentials credentials, String workspaceName)
- throws LoginException, NoSuchWorkspaceException,
- RepositoryException {
- Session session;
- try {
- session = getRepository().login(credentials, workspaceName);
- } catch (NoSuchWorkspaceException e) {
- if (autocreateWorkspaces && workspaceName != null)
- session = createWorkspaceAndLogsIn(credentials, workspaceName);
- else
- throw e;
}
- processNewSession(session);
- return session;
- }
- public Session login() throws LoginException, RepositoryException {
- return login(null, null);
- }
-
- public Session login(Credentials credentials) throws LoginException,
- RepositoryException {
- return login(credentials, null);
- }
-
- public Session login(String workspaceName) throws LoginException,
- NoSuchWorkspaceException, RepositoryException {
- return login(null, workspaceName);
- }
-
- /** Called after a session has been created, does nothing by default. */
- protected void processNewSession(Session session) {
- }
-
- public Boolean isRemote() {
- return uri != null;
- }
-
- /** Wraps access to the repository, making sure it is available. */
- protected Repository getRepository() {
- if (repository == null) {
- throw new ArgeoException("No repository initialized."
- + " Was the init() method called?"
- + " The destroy() method should also"
- + " be called on shutdown.");
+ Bundle exportingBundle = null;
+ if (exportedPackage != null) {
+ exportingBundle = exportedPackage.getExportingBundle();
+ } else {
+ throw new ArgeoException("No OSGi exporting package found for "
+ + resUrl);
}
- return repository;
- }
-
- /**
- * Logs in to the default workspace, creates the required workspace, logs
- * out, logs in to the required workspace.
- */
- protected Session createWorkspaceAndLogsIn(Credentials credentials,
- String workspaceName) throws RepositoryException {
- if (workspaceName == null)
- throw new ArgeoException("No workspace specified.");
- Session session = getRepository().login(credentials);
- session.getWorkspace().createWorkspace(workspaceName);
- session.logout();
- return getRepository().login(credentials, workspaceName);
- }
-
- public boolean isStandardDescriptor(String key) {
- return getRepository().isStandardDescriptor(key);
- }
-
- public boolean isSingleValueDescriptor(String key) {
- return getRepository().isSingleValueDescriptor(key);
- }
-
- public Value getDescriptorValue(String key) {
- return getRepository().getDescriptorValue(key);
- }
-
- public Value[] getDescriptorValues(String key) {
- return getRepository().getDescriptorValues(key);
+ return exportingBundle;
}
/*
* FIELDS ACCESS
*/
+ public void setNamespaces(Map<String, String> namespaces) {
+ this.namespaces = namespaces;
+ }
- public void setHomeDirectory(File homeDirectory) {
- this.homeDirectory = homeDirectory;
+ public void setCndFiles(List<String> cndFiles) {
+ this.cndFiles = cndFiles;
}
- public void setInMemory(Boolean inMemory) {
- this.inMemory = inMemory;
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
}
- public void setUri(String uri) {
- this.uri = uri;
+ public void setForceCndImport(Boolean forceCndUpdate) {
+ this.forceCndImport = forceCndUpdate;
}
- public void setRepository(Repository repository) {
- this.repository = repository;
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
}
}
private Boolean openSessionInView = true;
- private String securityWorkspace = "security";
+ private String defaultWorkspace = "default";
public Session getSession(HttpServletRequest request, Repository rep,
String workspace) throws LoginException, ServletException,
if (openSessionInView) {
JackrabbitSession session = (JackrabbitSession) rep
.login(workspace);
- if (session.getWorkspace().getName().equals(securityWorkspace))
+ if (session.getWorkspace().getName().equals(defaultWorkspace))
writeRemoteRoles(session);
return session;
} else {
JackrabbitSession session = (JackrabbitSession) rep.login(
null, workspace);
if (session.getWorkspace().getName()
- .equals(securityWorkspace))
+ .equals(defaultWorkspace))
writeRemoteRoles(session);
if (log.isTraceEnabled())
log.trace("User " + session.getUserID()
protected void writeRemoteRoles(JackrabbitSession session)
throws RepositoryException {
+ // FIXME better deal w/ non node repo
+
// retrieve roles
String userId = session.getUserID();
UserManager userManager = session.getUserManager();
userGroupIds.add(it.next().getID());
// write roles if needed
- Node userProfile = UserJcrUtils.getUserHome(session).getNode(
- ArgeoNames.ARGEO_PROFILE);
+ Node userHome = UserJcrUtils.getUserHome(session);
boolean writeRoles = false;
- if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
- Value[] roles = userProfile.getProperty(
- ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
+ if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+ Value[] roles = userHome.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES)
+ .getValues();
if (roles.length != userGroupIds.size())
writeRoles = true;
else
if (writeRoles) {
session.getWorkspace().getVersionManager()
- .checkout(userProfile.getPath());
+ .checkout(userHome.getPath());
String[] roleIds = userGroupIds.toArray(new String[userGroupIds
.size()]);
- userProfile.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
- JcrUtils.updateLastModified(userProfile);
+ userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
+ JcrUtils.updateLastModified(userHome);
session.save();
session.getWorkspace().getVersionManager()
- .checkin(userProfile.getPath());
+ .checkin(userHome.getPath());
}
}
}
public void setSecurityWorkspace(String securityWorkspace) {
- this.securityWorkspace = securityWorkspace;
+ this.defaultWorkspace = securityWorkspace;
}
}
*/
public static Repository getRepositoryByUri(
RepositoryFactory repositoryFactory, String uri) {
+ return getRepositoryByUri(repositoryFactory, uri, null);
+ }
+
+ /**
+ * Wraps the call to the repository factory based on parameter
+ * {@link ArgeoJcrConstants#JCR_REPOSITORY_URI} in order to simplify it and
+ * protect against future API changes.
+ */
+ public static Repository getRepositoryByUri(
+ RepositoryFactory repositoryFactory, String uri, String alias) {
try {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(JCR_REPOSITORY_URI, uri);
+ if (alias != null)
+ parameters.put(JCR_REPOSITORY_ALIAS, alias);
return repositoryFactory.getRepository(parameters);
} catch (RepositoryException e) {
throw new ArgeoException(
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Mathieu Baudier
+ *
+ * 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 org.argeo.jcr;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.argeo.ArgeoException;
+
+/**
+ * Wrapper around a JCR repository which allows to simplify configuration and
+ * intercept some actions. It exposes itself as a {@link Repository}.
+ */
+public abstract class JcrRepositoryWrapper implements Repository {
+ // private final static Log log = LogFactory
+ // .getLog(JcrRepositoryWrapper.class);
+
+ // wrapped repository
+ private Repository repository;
+
+ private Boolean autocreateWorkspaces = false;
+
+ /**
+ * Empty constructor, {@link #init()} should be called after properties have
+ * been set
+ */
+ public JcrRepositoryWrapper() {
+ }
+
+ /** Initializes */
+ public void init() {
+ }
+
+ /** Shutdown the repository */
+ public void destroy() throws Exception {
+ }
+
+ /*
+ * DELEGATED JCR REPOSITORY METHODS
+ */
+
+ public String getDescriptor(String key) {
+ return getRepository().getDescriptor(key);
+ }
+
+ public String[] getDescriptorKeys() {
+ return getRepository().getDescriptorKeys();
+ }
+
+ /** Central login method */
+ public Session login(Credentials credentials, String workspaceName)
+ throws LoginException, NoSuchWorkspaceException,
+ RepositoryException {
+ Session session;
+ try {
+ session = getRepository().login(credentials, workspaceName);
+ } catch (NoSuchWorkspaceException e) {
+ if (autocreateWorkspaces && workspaceName != null)
+ session = createWorkspaceAndLogsIn(credentials, workspaceName);
+ else
+ throw e;
+ }
+ processNewSession(session);
+ return session;
+ }
+
+ public Session login() throws LoginException, RepositoryException {
+ return login(null, null);
+ }
+
+ public Session login(Credentials credentials) throws LoginException,
+ RepositoryException {
+ return login(credentials, null);
+ }
+
+ public Session login(String workspaceName) throws LoginException,
+ NoSuchWorkspaceException, RepositoryException {
+ return login(null, workspaceName);
+ }
+
+ /** Called after a session has been created, does nothing by default. */
+ protected void processNewSession(Session session) {
+ }
+
+ /** Wraps access to the repository, making sure it is available. */
+ protected synchronized Repository getRepository() {
+// if (repository == null) {
+// throw new ArgeoException("No repository initialized."
+// + " Was the init() method called?"
+// + " The destroy() method should also"
+// + " be called on shutdown.");
+// }
+ return repository;
+ }
+
+ /**
+ * Logs in to the default workspace, creates the required workspace, logs
+ * out, logs in to the required workspace.
+ */
+ protected Session createWorkspaceAndLogsIn(Credentials credentials,
+ String workspaceName) throws RepositoryException {
+ if (workspaceName == null)
+ throw new ArgeoException("No workspace specified.");
+ Session session = getRepository().login(credentials);
+ session.getWorkspace().createWorkspace(workspaceName);
+ session.logout();
+ return getRepository().login(credentials, workspaceName);
+ }
+
+ public boolean isStandardDescriptor(String key) {
+ return getRepository().isStandardDescriptor(key);
+ }
+
+ public boolean isSingleValueDescriptor(String key) {
+ return getRepository().isSingleValueDescriptor(key);
+ }
+
+ public Value getDescriptorValue(String key) {
+ return getRepository().getDescriptorValue(key);
+ }
+
+ public Value[] getDescriptorValues(String key) {
+ return getRepository().getDescriptorValues(key);
+ }
+
+ public synchronized void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ public void setAutocreateWorkspaces(Boolean autocreateWorkspaces) {
+ this.autocreateWorkspaces = autocreateWorkspaces;
+ }
+
+}
[argeo:userHome] > mix:created, mix:lastModified
mixin
- argeo:userID (STRING) m
-+ argeo:profile (argeo:userProfile)
+- argeo:remoteRoles (STRING) *
+ argeo:keyring (argeo:pbeSpec)
+ argeo:preferences (argeo:preferenceNode)
- argeo:accountNonExpired (BOOLEAN)
- argeo:accountNonLocked (BOOLEAN)
- argeo:credentialsNonExpired (BOOLEAN)
-- argeo:remoteRoles (STRING) *
[argeo:preferenceNode] > mix:lastModified, mix:versionable
mixin