From: Bruno Sinou Date: Thu, 15 Sep 2016 13:38:42 +0000 (+0000) Subject: Moves JCR APIs to node.api bundle X-Git-Tag: argeo-commons-2.1.46~20 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=61780b581925666edd4bd7743a00dca7170f1d35;p=lgpl%2Fargeo-commons.git Moves JCR APIs to node.api bundle git-svn-id: https://svn.argeo.org/commons/trunk@9161 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/commands/AddRemoteRepository.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/commands/AddRemoteRepository.java index ba86eb71c..cf6a5b0f0 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/commands/AddRemoteRepository.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/commands/AddRemoteRepository.java @@ -28,11 +28,11 @@ import org.argeo.eclipse.ui.EclipseUiException; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.eclipse.ui.workbench.CommandUtils; import org.argeo.eclipse.ui.workbench.WorkbenchConstants; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; +import org.argeo.node.ArgeoNames; +import org.argeo.node.ArgeoTypes; +import org.argeo.node.NodeConstants; +import org.argeo.node.NodeUtils; import org.argeo.util.security.Keyring; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; @@ -143,7 +143,7 @@ public class AddRemoteRepository extends AbstractHandler implements String checkedUriStr = checkedUri.toString(); Hashtable params = new Hashtable(); - params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr); + params.put(NodeConstants.JCR_REPOSITORY_URI, checkedUriStr); Repository repository = repositoryFactory.getRepository(params); if (username.getText().trim().equals("")) {// anonymous session = repository.login(); @@ -170,7 +170,7 @@ public class AddRemoteRepository extends AbstractHandler implements Session nodeSession = null; try { nodeSession = nodeRepository.login(); - Node home = UserJcrUtils.getUserHome(nodeSession); + Node home = NodeUtils.getUserHome(nodeSession); Node remote = home.hasNode(ARGEO_REMOTE) ? home .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE); diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeContentProvider.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeContentProvider.java index 652da3fd8..243d93265 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeContentProvider.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeContentProvider.java @@ -29,9 +29,9 @@ import javax.jcr.nodetype.NodeType; import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.workbench.internal.jcr.model.RepositoriesElem; import org.argeo.eclipse.ui.workbench.internal.jcr.model.SingleJcrNodeElem; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.RepositoryRegister; -import org.argeo.jcr.UserJcrUtils; +import org.argeo.node.NodeConstants; +import org.argeo.node.NodeUtils; import org.argeo.util.security.Keyring; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; @@ -72,13 +72,13 @@ public class NodeContentProvider implements ITreeContentProvider { return; if (userSession != null) { - Node userHome = UserJcrUtils.getUserHome(userSession); + Node userHome = NodeUtils.getUserHome(userSession); if (userHome != null) { // TODO : find a way to dynamically get alias for the node if (homeNode != null) homeNode.dispose(); homeNode = new SingleJcrNodeElem(null, userHome, - userSession.getUserID(), ArgeoJcrConstants.ALIAS_NODE); + userSession.getUserID(), NodeConstants.ALIAS_NODE); } } if (repositoryRegister != null) { diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeLabelProvider.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeLabelProvider.java index 2ed6232a6..34f0398fc 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeLabelProvider.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/NodeLabelProvider.java @@ -28,7 +28,7 @@ import org.argeo.eclipse.ui.workbench.internal.jcr.model.RepositoryElem; import org.argeo.eclipse.ui.workbench.internal.jcr.model.SingleJcrNodeElem; import org.argeo.eclipse.ui.workbench.internal.jcr.model.WorkspaceElem; import org.argeo.eclipse.ui.workbench.jcr.JcrImages; -import org.argeo.jcr.ArgeoTypes; +import org.argeo.node.ArgeoTypes; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.swt.graphics.Image; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java index ec8db4aab..90acc034e 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java @@ -26,8 +26,8 @@ import javax.jcr.SimpleCredentials; import org.argeo.eclipse.ui.EclipseUiException; import org.argeo.eclipse.ui.TreeParent; -import org.argeo.jcr.ArgeoJcrUtils; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; +import org.argeo.node.NodeUtils; import org.argeo.util.security.Keyring; /** Root of a remote repository */ @@ -76,7 +76,7 @@ public class RemoteRepositoryElem extends RepositoryElem { @Override public Repository getRepository() { if (repository == null) - repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, + repository = NodeUtils.getRepositoryByUri(repositoryFactory, uri); return super.getRepository(); } diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RepositoriesElem.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RepositoriesElem.java index ceab362bc..864048a76 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RepositoriesElem.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RepositoriesElem.java @@ -27,9 +27,9 @@ import javax.jcr.Session; import org.argeo.eclipse.ui.EclipseUiException; import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.RepositoryRegister; -import org.argeo.jcr.UserJcrUtils; +import org.argeo.node.ArgeoNames; +import org.argeo.node.NodeUtils; import org.argeo.util.security.Keyring; /** @@ -96,7 +96,7 @@ public class RepositoriesElem extends TreeParent implements ArgeoNames { } protected void addRemoteRepositories(Keyring jcrKeyring) throws RepositoryException { - Node userHome = UserJcrUtils.getUserHome(userSession); + Node userHome = NodeUtils.getUserHome(userSession); if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) { NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes(); while (it.hasNext()) { diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/jcr/JcrPreferenceStore.java b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/jcr/JcrPreferenceStore.java index c90eec067..406baf929 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/jcr/JcrPreferenceStore.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/eclipse/ui/workbench/jcr/JcrPreferenceStore.java @@ -29,10 +29,10 @@ import javax.jcr.version.VersionManager; import org.apache.commons.io.IOUtils; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; +import org.argeo.node.ArgeoNames; +import org.argeo.node.ArgeoTypes; +import org.argeo.node.NodeUtils; import org.eclipse.jface.preference.PreferenceStore; import org.osgi.framework.BundleContext; @@ -54,7 +54,7 @@ public class JcrPreferenceStore extends PreferenceStore implements ArgeoNames { try { if (session.hasPendingChanges()) session.save(); - Node userHome = UserJcrUtils.getUserHome(session); + Node userHome = NodeUtils.getUserHome(session); if (userHome == null) throw new EclipseUiException("No user home for " + session.getUserID()); diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewGroup.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewGroup.java index 92aa7b1f8..e3abbbc43 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewGroup.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewGroup.java @@ -22,7 +22,7 @@ import org.argeo.cms.CmsException; import org.argeo.cms.ui.workbench.SecurityUiPlugin; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewUser.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewUser.java index 70afd8fd0..a7ec2d9b3 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewUser.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/commands/NewUser.java @@ -28,7 +28,7 @@ import org.argeo.cms.ui.workbench.SecurityUiPlugin; import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/DefaultUserMainPage.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/DefaultUserMainPage.java index 6529efe30..3fe07f782 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/DefaultUserMainPage.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/DefaultUserMainPage.java @@ -24,7 +24,7 @@ import javax.jcr.RepositoryException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java index fe56679db..b48726f48 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupMainPage.java @@ -26,7 +26,7 @@ import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminImages; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java index 88f163326..f7ad517a5 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/GroupsView.java @@ -27,7 +27,7 @@ import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.internal.UiUserAdminListener; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java index 31b2042b6..b3bff5943 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserBatchUpdateWizard.java @@ -16,7 +16,7 @@ import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.internal.UserAdminWrapper; import org.argeo.security.ui.admin.internal.providers.CommonNameLP; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java index db6eb538f..df910ecea 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UserMainPage.java @@ -25,7 +25,7 @@ import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.SecurityAdminImages; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UsersView.java b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UsersView.java index 2503223b6..a811cd5a5 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UsersView.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/security/ui/admin/internal/parts/UsersView.java @@ -25,7 +25,7 @@ import org.argeo.cms.util.useradmin.UserAdminUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.ArgeoNames; +import org.argeo.node.ArgeoNames; import org.argeo.osgi.useradmin.LdifName; import org.argeo.security.ui.admin.internal.UiUserAdminListener; import org.argeo.security.ui.admin.internal.UserAdminWrapper; diff --git a/org.argeo.cms.ui/src/org/argeo/cms/maintenance/DataDeploymentUi.java b/org.argeo.cms.ui/src/org/argeo/cms/maintenance/DataDeploymentUi.java index efcbaa991..12539a597 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/maintenance/DataDeploymentUi.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/maintenance/DataDeploymentUi.java @@ -10,7 +10,7 @@ import java.util.Collection; import org.apache.jackrabbit.core.RepositoryContext; import org.apache.jackrabbit.core.config.RepositoryConfig; import org.argeo.cms.util.CmsUtils; -import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.node.NodeConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -82,12 +82,12 @@ class DataDeploymentUi extends AbstractOsgiComposite { private void initCurrentUi(Composite parent) { parent.setLayout(new GridLayout()); Collection> contexts = getServiceReferences(RepositoryContext.class, - "(" + ArgeoJcrConstants.JCR_REPOSITORY_ALIAS + "=*)"); + "(" + NodeConstants.JCR_REPOSITORY_ALIAS + "=*)"); StringBuffer text = new StringBuffer(); text.append("Jackrabbit Repositories
"); for (ServiceReference sr : contexts) { RepositoryContext repositoryContext = bc.getService(sr); - String alias = sr.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS).toString(); + String alias = sr.getProperty(NodeConstants.JCR_REPOSITORY_ALIAS).toString(); String rootNodeId = repositoryContext.getRootNodeId().toString(); RepositoryConfig repositoryConfig = repositoryContext.getRepositoryConfig(); Path repoHomePath = new File(repositoryConfig.getHomeDir()).toPath().toAbsolutePath(); diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java b/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java index a19081062..a21c05a72 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java @@ -18,9 +18,9 @@ import org.argeo.cms.auth.AuthConstants; import org.argeo.cms.ui.CmsConstants; import org.argeo.cms.ui.CmsView; import org.argeo.eclipse.ui.specific.UiContext; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.JcrUtils; import org.argeo.node.NodeAuthenticated; +import org.argeo.node.NodeConstants; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.service.ResourceManager; import org.eclipse.swt.SWT; @@ -86,7 +86,7 @@ public class CmsUtils implements CmsConstants { else buf.append(WEBDAV_PRIVATE); // TODO convey repo alias vie repository properties - return buf.append('/').append(ArgeoJcrConstants.ALIAS_NODE).append('/').append(node.getSession().getWorkspace().getName()) + return buf.append('/').append(NodeConstants.ALIAS_NODE).append('/').append(node.getSession().getWorkspace().getName()) .append(node.getPath()).toString(); } // diff --git a/org.argeo.cms/.classpath b/org.argeo.cms/.classpath index eca7bdba8..53c7dca0b 100644 --- a/org.argeo.cms/.classpath +++ b/org.argeo.cms/.classpath @@ -3,5 +3,6 @@ + diff --git a/org.argeo.cms/build.properties b/org.argeo.cms/build.properties index 4f7e63bdb..e8ee67116 100644 --- a/org.argeo.cms/build.properties +++ b/org.argeo.cms/build.properties @@ -5,4 +5,6 @@ bin.includes = META-INF/,\ bin/,\ OSGI-INF/org.argeo.cms.internal.kernel.KernelInitOld.xml source.. = src/ -additional.bundles = org.apache.jackrabbit.data +additional.bundles = org.apache.jackrabbit.data,\ + org.argeo.jcr,\ + org.junit diff --git a/org.argeo.cms/ext/test/org/argeo/cms/tabular/JcrTabularTest.java b/org.argeo.cms/ext/test/org/argeo/cms/tabular/JcrTabularTest.java new file mode 100644 index 000000000..0d8a8ce5f --- /dev/null +++ b/org.argeo.cms/ext/test/org/argeo/cms/tabular/JcrTabularTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.cms.tabular; + +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.PropertyType; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.commons.cnd.CndImporter; +import org.argeo.cms.tabular.JcrTabularRowIterator; +import org.argeo.cms.tabular.JcrTabularWriter; +import org.argeo.jackrabbit.unit.AbstractJackrabbitTestCase; +import org.argeo.node.ArgeoNames; +import org.argeo.node.ArgeoTypes; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularRow; +import org.argeo.util.tabular.TabularRowIterator; +import org.argeo.util.tabular.TabularWriter; + +public class JcrTabularTest extends AbstractJackrabbitTestCase { + private final static Log log = LogFactory.getLog(JcrTabularTest.class); + + public void testWriteReadCsv() throws Exception { + session().setNamespacePrefix("argeo", ArgeoNames.ARGEO_NAMESPACE); + InputStreamReader reader = new InputStreamReader(getClass() + .getResourceAsStream("/org/argeo/node/node.cnd")); + CndImporter.registerNodeTypes(reader, session()); + reader.close(); + + // write + Integer columnCount = 15; + Long rowCount = 1000l; + String stringValue = "test, \ntest"; + + List header = new ArrayList(); + for (int i = 0; i < columnCount; i++) { + header.add(new TabularColumn("col" + i, PropertyType.STRING)); + } + Node tableNode = session().getRootNode().addNode("table", + ArgeoTypes.ARGEO_TABLE); + TabularWriter writer = new JcrTabularWriter(tableNode, header, + ArgeoTypes.ARGEO_CSV); + for (int i = 0; i < rowCount; i++) { + List objs = new ArrayList(); + for (int j = 0; j < columnCount; j++) { + objs.add(stringValue); + } + writer.appendRow(objs.toArray()); + } + writer.close(); + session().save(); + + if (log.isDebugEnabled()) + log.debug("Wrote tabular content " + rowCount + " rows, " + + columnCount + " columns"); + // read + TabularRowIterator rowIt = new JcrTabularRowIterator(tableNode); + Long count = 0l; + while (rowIt.hasNext()) { + TabularRow tr = rowIt.next(); + assertEquals(header.size(), tr.size()); + count++; + } + assertEquals(rowCount, count); + if (log.isDebugEnabled()) + log.debug("Read tabular content " + rowCount + " rows, " + + columnCount + " columns"); + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index 19dc8d9b8..0373e3690 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -20,7 +20,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.commons.cnd.CndImporter; import org.apache.jackrabbit.core.RepositoryContext; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.JcrUtils; import org.argeo.node.DataModelNamespace; import org.argeo.node.NodeConstants; @@ -130,8 +129,8 @@ public class CmsDeployment implements NodeDeployment { prepareDataModel(KernelUtils.openAdminSession(deployedNodeRepository)); Hashtable regProps = new Hashtable(); - regProps.put(NodeConstants.CN, ArgeoJcrConstants.ALIAS_HOME); - regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_HOME); + regProps.put(NodeConstants.CN, NodeConstants.ALIAS_HOME); + regProps.put(NodeConstants.JCR_REPOSITORY_ALIAS, NodeConstants.ALIAS_HOME); homeRepository = new HomeRepository(deployedNodeRepository); // register bc.registerService(Repository.class, homeRepository, regProps); @@ -186,9 +185,9 @@ public class CmsDeployment implements NodeDeployment { if (!asBoolean((String) attrs.get(DataModelNamespace.CAPABILITY_ABSTRACT_ATTRIBUTE))) { Hashtable properties = new Hashtable<>(); - properties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, name); + properties.put(NodeConstants.JCR_REPOSITORY_ALIAS, name); properties.put(NodeConstants.CN, name); - if (name.equals(ArgeoJcrConstants.ALIAS_NODE)) + if (name.equals(NodeConstants.ALIAS_NODE)) properties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); LocalRepository localRepository = new LocalRepository(adminSession.getRepository(), capability); bc.registerService(Repository.class, localRepository, properties); @@ -226,7 +225,7 @@ public class CmsDeployment implements NodeDeployment { public RepositoryContext addingService(ServiceReference reference) { RepositoryContext nodeRepo = bc.getService(reference); Object cn = reference.getProperty(NodeConstants.CN); - if (cn != null && cn.equals(ArgeoJcrConstants.ALIAS_NODE)) { + if (cn != null && cn.equals(NodeConstants.ALIAS_NODE)) { prepareNodeRepository(nodeRepo.getRepository()); nodeAvailable = true; checkReadiness(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsInstance.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsInstance.java index 795f063fb..fb3e6ad4d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsInstance.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsInstance.java @@ -4,7 +4,6 @@ import javax.jcr.Repository; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.node.NodeConstants; import org.argeo.node.NodeInstance; import org.osgi.framework.BundleContext; @@ -27,7 +26,7 @@ public class CmsInstance implements NodeInstance { @Override public Repository addingService(ServiceReference reference) { Object cn = reference.getProperty(NodeConstants.CN); - if (cn != null && cn.equals(ArgeoJcrConstants.ALIAS_NODE)) { + if (cn != null && cn.equals(NodeConstants.ALIAS_NODE)) { if (log.isDebugEnabled()) log.debug("Node repository is available"); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java index 88f79c5ea..e7d9460ce 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java @@ -35,8 +35,8 @@ import org.argeo.cms.CmsException; import org.argeo.cms.auth.AuthConstants; import org.argeo.cms.auth.HttpRequestCallback; import org.argeo.cms.auth.HttpRequestCallbackHandler; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.JcrUtils; +import org.argeo.node.NodeConstants; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; @@ -51,7 +51,7 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer; * Intercepts and enriches http access, mainly focusing on security and * transactionality. */ -class DataHttp implements KernelConstants, ArgeoJcrConstants { +class DataHttp implements KernelConstants { private final static Log log = LogFactory.getLog(DataHttp.class); // private final static String ATTR_AUTH = "auth"; @@ -161,7 +161,7 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants { @Override public Repository addingService(ServiceReference reference) { Repository repository = bc.getService(reference); - Object jcrRepoAlias = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); + Object jcrRepoAlias = reference.getProperty(NodeConstants.JCR_REPOSITORY_ALIAS); if (jcrRepoAlias != null) { String alias = jcrRepoAlias.toString(); registerRepositoryServlets(alias, repository); @@ -175,7 +175,7 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants { @Override public void removedService(ServiceReference reference, Repository service) { - Object jcrRepoAlias = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); + Object jcrRepoAlias = reference.getProperty(NodeConstants.JCR_REPOSITORY_ALIAS); if (jcrRepoAlias != null) { String alias = jcrRepoAlias.toString(); unregisterRepositoryServlets(alias); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java index 80bd91247..042d1f634 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java @@ -19,7 +19,6 @@ import javax.naming.ldap.Rdn; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.node.NodeConstants; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.util.naming.AttributesDictionary; @@ -69,7 +68,7 @@ class DeployConfig implements ConfigurationListener { // node repository Dictionary nodeConfig = firstInit - .getNodeRepositoryConfig(getProps(NodeConstants.NODE_REPOS_FACTORY_PID, ArgeoJcrConstants.ALIAS_NODE)); + .getNodeRepositoryConfig(getProps(NodeConstants.NODE_REPOS_FACTORY_PID, NodeConstants.ALIAS_NODE)); // node repository is mandatory putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, nodeConfig); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInitProperties.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInitProperties.java index 2a054d5be..b0af36366 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInitProperties.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInitProperties.java @@ -16,7 +16,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.node.NodeConstants; import org.argeo.node.RepoConf; import org.argeo.osgi.useradmin.UserAdminConf; @@ -41,8 +40,8 @@ class FirstInitProperties { if (value != null) props.put(repoConf.name(), value); } - props.put(NodeConstants.CN, ArgeoJcrConstants.ALIAS_NODE); - props.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE); + props.put(NodeConstants.CN, NodeConstants.ALIAS_NODE); + props.put(NodeConstants.JCR_REPOSITORY_ALIAS, NodeConstants.ALIAS_NODE); return props; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/HomeRepository.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/HomeRepository.java index c6f3a600d..237f16fb3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/HomeRepository.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/HomeRepository.java @@ -17,20 +17,20 @@ import javax.security.auth.login.LoginContext; import org.apache.jackrabbit.core.security.SecurityConstants; import org.argeo.cms.CmsException; import org.argeo.cms.auth.AuthConstants; -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.argeo.jcr.UserJcrUtils; +import org.argeo.node.ArgeoNames; +import org.argeo.node.ArgeoTypes; +import org.argeo.node.NodeConstants; +import org.argeo.node.NodeUtils; /** * Make sure each user has a home directory available in the default workspace. */ -class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, ArgeoJcrConstants { +class HomeRepository extends JcrRepositoryWrapper implements KernelConstants { /** The home base path. */ private String homeBasePath = "/home"; - private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH; + private String peopleBasePath = NodeConstants.PEOPLE_BASE_PATH; private Set checkedUsers = new HashSet(); @@ -94,7 +94,8 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar if (checkedUsers.contains(username)) return; - Session adminSession = KernelUtils.openAdminSession(getRepository(), session.getWorkspace().getName()); + Session adminSession = KernelUtils.openAdminSession(getRepository(), + session.getWorkspace().getName()); try { syncJcr(adminSession, username); checkedUsers.add(username); @@ -113,8 +114,10 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar JcrUtils.mkdirs(adminSession, peopleBasePath); adminSession.save(); - JcrUtils.addPrivilege(adminSession, homeBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); - JcrUtils.addPrivilege(adminSession, peopleBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL); + JcrUtils.addPrivilege(adminSession, homeBasePath, + AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); + JcrUtils.addPrivilege(adminSession, peopleBasePath, + AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL); adminSession.save(); } catch (RepositoryException e) { throw new CmsException("Cannot initialize node user admin", e); @@ -125,11 +128,12 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar private Node syncJcr(Session session, String username) { try { - Node userHome = UserJcrUtils.getUserHome(session, username); + Node userHome = NodeUtils.getUserHome(session, username); if (userHome == null) { String homePath = generateUserPath(homeBasePath, username); if (session.itemExists(homePath))// duplicate user id - userHome = session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath)); + userHome = session.getNode(homePath).getParent() + .addNode(JcrUtils.lastPathElement(homePath)); else userHome = JcrUtils.mkdirs(session, homePath); // userHome = JcrUtils.mkfolders(session, homePath); @@ -138,16 +142,18 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar session.save(); JcrUtils.clearAccessControList(session, homePath, username); - JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL); + JcrUtils.addPrivilege(session, homePath, username, + Privilege.JCR_ALL); } - Node userProfile = UserJcrUtils.getUserProfile(session, username); + Node userProfile = NodeUtils.getUserProfile(session, username); // new user if (userProfile == null) { String personPath = generateUserPath(peopleBasePath, username); Node personBase; if (session.itemExists(personPath))// duplicate user id - personBase = session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath)); + personBase = session.getNode(personPath).getParent() + .addNode(JcrUtils.lastPathElement(personPath)); else personBase = JcrUtils.mkdirs(session, personPath); userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE); @@ -162,8 +168,10 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar // true); session.save(); - JcrUtils.clearAccessControList(session, userProfile.getPath(), username); - JcrUtils.addPrivilege(session, userProfile.getPath(), username, Privilege.JCR_READ); + JcrUtils.clearAccessControList(session, userProfile.getPath(), + username); + JcrUtils.addPrivilege(session, userProfile.getPath(), username, + Privilege.JCR_READ); } // Remote roles @@ -175,7 +183,8 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar return userProfile; } catch (RepositoryException e) { JcrUtils.discardQuietly(session); - throw new CmsException("Cannot sync node security model for " + username, e); + throw new CmsException("Cannot sync node security model for " + + username, e); } } @@ -192,12 +201,14 @@ class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, Ar if (atIndex > 0) { String domain = userId.substring(0, atIndex); String name = userId.substring(atIndex + 1); - return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain + '/' - + JcrUtils.firstCharsToPath(name, 2) + '/' + name; + return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + + domain + '/' + JcrUtils.firstCharsToPath(name, 2) + '/' + + name; } else if (atIndex == 0 || atIndex == (userId.length() - 1)) { throw new CmsException("Unsupported username " + userId); } else { - return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId; + return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + + userId; } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JcrKeyring.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JcrKeyring.java new file mode 100644 index 000000000..396093ff7 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JcrKeyring.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.cms.internal.kernel; + +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.InputStream; +import java.io.Reader; +import java.security.Provider; +import java.security.SecureRandom; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.io.IOUtils; +import org.argeo.jcr.ArgeoJcrException; +import org.argeo.jcr.JcrUtils; +import org.argeo.node.ArgeoNames; +import org.argeo.node.ArgeoTypes; +import org.argeo.node.NodeUtils; +import org.argeo.util.security.AbstractKeyring; +import org.argeo.util.security.PBEKeySpecCallback; + +/** JCR based implementation of a keyring */ +public class JcrKeyring extends AbstractKeyring implements ArgeoNames { + /** + * Stronger with 256, but causes problem with Oracle JVM, force 128 in this + * case + */ + public final static Long DEFAULT_SECRETE_KEY_LENGTH = 256l; + public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; + public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; + public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; + + private Integer iterationCountFactor = 200; + private Long secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; + private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; + private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; + private String cipherName = DEFAULT_CIPHER_NAME; + + private Session session; + + /** + * When setup is called the session has not yet been saved and we don't want + * to save it since there maybe other data which would be inconsistent. So + * we keep a reference to this node which will then be used (an reset to + * null) when handling the PBE callback. We keep one per thread in case + * multiple users are accessing the same instance of a keyring. + */ + private ThreadLocal notYetSavedKeyring = new ThreadLocal() { + + @Override + protected Node initialValue() { + return null; + } + }; + + @Override + protected Boolean isSetup() { + try { + if (notYetSavedKeyring.get() != null) + return true; + + Node userHome = NodeUtils.getUserHome(session); + return userHome.hasNode(ARGEO_KEYRING); + } catch (RepositoryException e) { + throw new ArgeoJcrException("Cannot check whether keyring is setup", e); + } + } + + @Override + protected void setup(char[] password) { + Binary binary = null; + InputStream in = null; + try { + Node userHome = NodeUtils.getUserHome(session); + if (userHome.hasNode(ARGEO_KEYRING)) + throw new ArgeoJcrException("Keyring already setup"); + Node keyring = userHome.addNode(ARGEO_KEYRING); + keyring.addMixin(ArgeoTypes.ARGEO_PBE_SPEC); + + // deterministic salt and iteration count based on username + String username = session.getUserID(); + byte[] salt = new byte[8]; + byte[] usernameBytes = username.getBytes(); + for (int i = 0; i < salt.length; i++) { + if (i < usernameBytes.length) + salt[i] = usernameBytes[i]; + else + salt[i] = 0; + } + in = new ByteArrayInputStream(salt); + binary = session.getValueFactory().createBinary(in); + keyring.setProperty(ARGEO_SALT, binary); + + Integer iterationCount = username.length() * iterationCountFactor; + keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); + + // default algo + // TODO check if algo and key length are available, use DES if not + keyring.setProperty(ARGEO_SECRET_KEY_FACTORY, secreteKeyFactoryName); + keyring.setProperty(ARGEO_KEY_LENGTH, secreteKeyLength); + keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, secreteKeyEncryption); + keyring.setProperty(ARGEO_CIPHER, cipherName); + + // keyring.getSession().save(); + + // encrypted password hash + // IOUtils.closeQuietly(in); + // JcrUtils.closeQuietly(binary); + // byte[] btPass = hash(password, salt, iterationCount); + // in = new ByteArrayInputStream(btPass); + // binary = session.getValueFactory().createBinary(in); + // keyring.setProperty(ARGEO_PASSWORD, binary); + + notYetSavedKeyring.set(keyring); + } catch (Exception e) { + throw new ArgeoJcrException("Cannot setup keyring", e); + } finally { + JcrUtils.closeQuietly(binary); + IOUtils.closeQuietly(in); + // JcrUtils.discardQuietly(session); + } + } + + @Override + protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { + try { + Node userHome = NodeUtils.getUserHome(session); + Node keyring; + if (userHome.hasNode(ARGEO_KEYRING)) + keyring = userHome.getNode(ARGEO_KEYRING); + else if (notYetSavedKeyring.get() != null) + keyring = notYetSavedKeyring.get(); + else + throw new ArgeoJcrException("Keyring not setup"); + + pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY).getString(), + JcrUtils.getBinaryAsBytes(keyring.getProperty(ARGEO_SALT)), + (int) keyring.getProperty(ARGEO_ITERATION_COUNT).getLong(), + (int) keyring.getProperty(ARGEO_KEY_LENGTH).getLong(), + keyring.getProperty(ARGEO_SECRET_KEY_ENCRYPTION).getString()); + + if (notYetSavedKeyring.get() != null) + notYetSavedKeyring.remove(); + } catch (RepositoryException e) { + throw new ArgeoJcrException("Cannot handle key spec callback", e); + } + } + + /** The parent node must already exist at this path. */ + @Override + protected synchronized void encrypt(String path, InputStream unencrypted) { + // should be called first for lazy initialization + SecretKey secretKey = getSecretKey(); + + Binary binary = null; + InputStream in = null; + try { + Cipher cipher = createCipher(); + Node node; + if (!session.nodeExists(path)) { + String parentPath = JcrUtils.parentPath(path); + if (!session.nodeExists(parentPath)) + throw new ArgeoJcrException("No parent node of " + path); + Node parentNode = session.getNode(parentPath); + node = parentNode.addNode(JcrUtils.nodeNameFromPath(path)); + } else { + node = session.getNode(path); + } + node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); + SecureRandom random = new SecureRandom(); + byte[] iv = new byte[16]; + random.nextBytes(iv); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); + JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); + + in = new CipherInputStream(unencrypted, cipher); + binary = session.getValueFactory().createBinary(in); + node.setProperty(Property.JCR_DATA, binary); + session.save(); + } catch (Exception e) { + throw new ArgeoJcrException("Cannot encrypt", e); + } finally { + IOUtils.closeQuietly(unencrypted); + IOUtils.closeQuietly(in); + JcrUtils.closeQuietly(binary); + } + } + + @Override + protected synchronized InputStream decrypt(String path) { + Binary binary = null; + InputStream encrypted = null; + Reader reader = null; + try { + if (!session.nodeExists(path)) { + char[] password = ask(); + reader = new CharArrayReader(password); + return new ByteArrayInputStream(IOUtils.toByteArray(reader)); + } else { + // should be called first for lazy initialisation + SecretKey secretKey = getSecretKey(); + + Cipher cipher = createCipher(); + + Node node = session.getNode(path); + if (node.hasProperty(ARGEO_IV)) { + byte[] iv = JcrUtils.getBinaryAsBytes(node.getProperty(ARGEO_IV)); + cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); + } else { + cipher.init(Cipher.DECRYPT_MODE, secretKey); + } + + binary = node.getProperty(Property.JCR_DATA).getBinary(); + encrypted = binary.getStream(); + return new CipherInputStream(encrypted, cipher); + } + } catch (Exception e) { + throw new ArgeoJcrException("Cannot decrypt", e); + } finally { + IOUtils.closeQuietly(encrypted); + IOUtils.closeQuietly(reader); + JcrUtils.closeQuietly(binary); + } + } + + protected Cipher createCipher() { + try { + Node userHome = NodeUtils.getUserHome(session); + if (!userHome.hasNode(ARGEO_KEYRING)) + throw new ArgeoJcrException("Keyring not setup"); + Node keyring = userHome.getNode(ARGEO_KEYRING); + String cipherName = keyring.getProperty(ARGEO_CIPHER).getString(); + Provider securityProvider = getSecurityProvider(); + Cipher cipher; + if (securityProvider == null)// TODO use BC? + cipher = Cipher.getInstance(cipherName); + else + cipher = Cipher.getInstance(cipherName, securityProvider); + return cipher; + } catch (Exception e) { + throw new ArgeoJcrException("Cannot get cipher", e); + } + } + + public synchronized void changePassword(char[] oldPassword, char[] newPassword) { + // TODO decrypt with old pw / encrypt with new pw all argeo:encrypted + } + + public synchronized void setSession(Session session) { + this.session = session; + } + + public void setIterationCountFactor(Integer iterationCountFactor) { + this.iterationCountFactor = iterationCountFactor; + } + + public void setSecreteKeyLength(Long keyLength) { + this.secreteKeyLength = keyLength; + } + + public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { + this.secreteKeyFactoryName = secreteKeyFactoryName; + } + + public void setSecreteKeyEncryption(String secreteKeyEncryption) { + this.secreteKeyEncryption = secreteKeyEncryption; + } + + public void setCipherName(String cipherName) { + this.cipherName = cipherName; + } + +} \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java index 50f7ef322..37c25d007 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java @@ -30,7 +30,7 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.argeo.cms.CmsException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.node.NodeConstants; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; @@ -250,7 +250,7 @@ class KernelUtils implements KernelConstants { else buf.append(WEBDAV_PRIVATE); // TODO convey repo alias vie repository properties - return buf.append('/').append(ArgeoJcrConstants.ALIAS_NODE).append('/').append(node.getSession().getWorkspace().getName()) + return buf.append('/').append(NodeConstants.ALIAS_NODE).append('/').append(node.getSession().getWorkspace().getName()) .append(node.getPath()).toString(); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java index 4a6ad2337..0510b3c83 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java @@ -29,8 +29,8 @@ import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.JcrUtils; +import org.argeo.node.NodeConstants; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; @@ -39,7 +39,7 @@ import org.osgi.service.http.HttpService; * Intercepts and enriches http access, mainly focusing on security and * transactionality. */ -class NodeHttp implements KernelConstants, ArgeoJcrConstants { +class NodeHttp implements KernelConstants { private final static Log log = LogFactory.getLog(NodeHttp.class); // Filters @@ -116,7 +116,7 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { @Override public Session run() throws Exception { Collection> srs = bc.getServiceReferences(Repository.class, "(" - + ArgeoJcrConstants.JCR_REPOSITORY_ALIAS + "=" + ArgeoJcrConstants.ALIAS_NODE + ")"); + + NodeConstants.JCR_REPOSITORY_ALIAS + "=" + NodeConstants.ALIAS_NODE + ")"); Repository repository = bc.getService(srs.iterator().next()); return repository.login(); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java index abfb44642..0fc028f49 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java @@ -24,12 +24,9 @@ import org.apache.jackrabbit.core.cache.CacheManager; import org.apache.jackrabbit.core.config.RepositoryConfig; import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.ArgeoJcrException; import org.argeo.node.NodeConstants; import org.argeo.node.RepoConf; -import org.osgi.framework.Constants; -import org.osgi.service.cm.ConfigurationAdmin; import org.xml.sax.InputSource; /** Can interpret properties in order to create an actual JCR repository. */ diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java index 1355f852c..f69c498e3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java @@ -8,7 +8,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.core.RepositoryContext; import org.argeo.cms.CmsException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.node.NodeConstants; import org.argeo.util.LangUtils; import org.osgi.framework.BundleContext; @@ -52,7 +51,7 @@ class RepositoryServiceFactory implements ManagedServiceFactory { Object cn = properties.get(NodeConstants.CN); if (cn != null) { props.put(NodeConstants.CN, cn); - props.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, cn); + props.put(NodeConstants.JCR_REPOSITORY_ALIAS, cn); pidToCn.put(pid, cn); } bc.registerService(RepositoryContext.class, repositoryContext, props); diff --git a/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularRowIterator.java b/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularRowIterator.java new file mode 100644 index 000000000..931a2b565 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularRowIterator.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.cms.tabular; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.argeo.jcr.ArgeoJcrException; +import org.argeo.node.ArgeoTypes; +import org.argeo.util.CsvParser; +import org.argeo.util.tabular.ArrayTabularRow; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularRow; +import org.argeo.util.tabular.TabularRowIterator; + +/** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */ +public class JcrTabularRowIterator implements TabularRowIterator { + private Boolean hasNext = null; + private Boolean parsingCompleted = false; + + private Long currentRowNumber = 0l; + + private List header = new ArrayList(); + + /** referenced so that we can close it */ + private Binary binary; + private InputStream in; + + private CsvParser csvParser; + private ArrayBlockingQueue> textLines; + + public JcrTabularRowIterator(Node tableNode) { + try { + for (NodeIterator it = tableNode.getNodes(); it.hasNext();) { + Node node = it.nextNode(); + if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) { + Integer type = PropertyType.valueFromName(node.getProperty( + Property.JCR_REQUIRED_TYPE).getString()); + TabularColumn tc = new TabularColumn(node.getProperty( + Property.JCR_TITLE).getString(), type); + header.add(tc); + } + } + Node contentNode = tableNode.getNode(Property.JCR_CONTENT); + if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) { + textLines = new ArrayBlockingQueue>(1000); + csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, + List header, List tokens) { + try { + textLines.put(tokens); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // textLines.add(tokens); + if (hasNext == null) { + hasNext = true; + synchronized (JcrTabularRowIterator.this) { + JcrTabularRowIterator.this.notifyAll(); + } + } + } + }; + csvParser.setNoHeader(true); + binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); + in = binary.getStream(); + Thread thread = new Thread(contentNode.getPath() + " reader") { + public void run() { + try { + csvParser.parse(in); + } finally { + parsingCompleted = true; + IOUtils.closeQuietly(in); + } + } + }; + thread.start(); + } + } catch (RepositoryException e) { + throw new ArgeoJcrException("Cannot read table " + tableNode, e); + } + } + + public synchronized boolean hasNext() { + // we don't know if there is anything available + // while (hasNext == null) + // try { + // wait(); + // } catch (InterruptedException e) { + // // silent + // // FIXME better deal with interruption + // Thread.currentThread().interrupt(); + // break; + // } + + // buffer not empty + if (!textLines.isEmpty()) + return true; + + // maybe the parsing is finished but the flag has not been set + while (!parsingCompleted && textLines.isEmpty()) + try { + wait(100); + } catch (InterruptedException e) { + // silent + // FIXME better deal with interruption + Thread.currentThread().interrupt(); + break; + } + + // buffer not empty + if (!textLines.isEmpty()) + return true; + + // (parsingCompleted && textLines.isEmpty()) + return false; + + // if (!hasNext && textLines.isEmpty()) { + // if (in != null) { + // IOUtils.closeQuietly(in); + // in = null; + // } + // if (binary != null) { + // JcrUtils.closeQuietly(binary); + // binary = null; + // } + // return false; + // } else + // return true; + } + + public synchronized TabularRow next() { + try { + List tokens = textLines.take(); + List objs = new ArrayList(tokens.size()); + for (String token : tokens) { + // TODO convert to other formats using header + objs.add(token); + } + currentRowNumber++; + return new ArrayTabularRow(objs); + } catch (InterruptedException e) { + // silent + // FIXME better deal with interruption + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Long getCurrentRowNumber() { + return currentRowNumber; + } + + public List getHeader() { + return header; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularWriter.java b/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularWriter.java new file mode 100644 index 000000000..7249fd509 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularWriter.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.cms.tabular; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.List; + +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.argeo.jcr.ArgeoJcrException; +import org.argeo.jcr.JcrUtils; +import org.argeo.node.ArgeoTypes; +import org.argeo.util.CsvWriter; +import org.argeo.util.tabular.TabularColumn; +import org.argeo.util.tabular.TabularWriter; + +/** Write / reference tabular content in a JCR repository. */ +public class JcrTabularWriter implements TabularWriter { + private Node contentNode; + private ByteArrayOutputStream out; + private CsvWriter csvWriter; + + @SuppressWarnings("unused") + private final List columns; + + /** Creates a table node */ + public JcrTabularWriter(Node tableNode, List columns, + String contentNodeType) { + try { + this.columns = columns; + for (TabularColumn column : columns) { + String normalized = JcrUtils.replaceInvalidChars(column + .getName()); + Node columnNode = tableNode.addNode(normalized, + ArgeoTypes.ARGEO_COLUMN); + columnNode.setProperty(Property.JCR_TITLE, column.getName()); + if (column.getType() != null) + columnNode.setProperty(Property.JCR_REQUIRED_TYPE, + PropertyType.nameFromValue(column.getType())); + else + columnNode.setProperty(Property.JCR_REQUIRED_TYPE, + PropertyType.TYPENAME_STRING); + } + contentNode = tableNode.addNode(Property.JCR_CONTENT, + contentNodeType); + if (contentNodeType.equals(ArgeoTypes.ARGEO_CSV)) { + contentNode.setProperty(Property.JCR_MIMETYPE, "text/csv"); + contentNode.setProperty(Property.JCR_ENCODING, "UTF-8"); + out = new ByteArrayOutputStream(); + csvWriter = new CsvWriter(out); + } + } catch (RepositoryException e) { + throw new ArgeoJcrException("Cannot create table node " + tableNode, e); + } + } + + public void appendRow(Object[] row) { + csvWriter.writeLine(row); + } + + public void close() { + Binary binary = null; + InputStream in = null; + try { + // TODO parallelize with pipes and writing from another thread + in = new ByteArrayInputStream(out.toByteArray()); + binary = contentNode.getSession().getValueFactory() + .createBinary(in); + contentNode.setProperty(Property.JCR_DATA, binary); + } catch (RepositoryException e) { + throw new ArgeoJcrException("Cannot store data in " + contentNode, e); + } finally { + IOUtils.closeQuietly(in); + JcrUtils.closeQuietly(binary); + } + } +} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/JcrUsersTable.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/JcrUsersTable.java index 0b8b3b262..9ae89a171 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/JcrUsersTable.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/JcrUsersTable.java @@ -1,364 +1,321 @@ package org.argeo.eclipse.ui.parts; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.QueryManager; -import javax.jcr.query.QueryResult; -import javax.jcr.query.qom.Constraint; -import javax.jcr.query.qom.Ordering; -import javax.jcr.query.qom.QueryObjectModel; -import javax.jcr.query.qom.QueryObjectModelFactory; -import javax.jcr.query.qom.Selector; -import javax.jcr.query.qom.StaticOperand; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.jcr.JcrUiUtils; -import org.argeo.eclipse.ui.jcr.lists.JcrColumnDefinition; -import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; -import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider; -import org.argeo.eclipse.ui.utils.ViewerUtils; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.Text; - +@Deprecated +public class JcrUsersTable { +} /** * Composite that contains a JFace table to display users that are stored in JCR * following the Argeo Conventions (See {@link ArgeoNames} */ -public class JcrUsersTable extends Composite implements ArgeoNames { - // private final static Log log = - // LogFactory.getLog(UserTableComposite.class); - - private static final long serialVersionUID = -7385959046279360420L; - - private Session session; - - private boolean hasFilter; - private boolean hasSelectionColumn; - private int tableStyle; - - private TableViewer usersViewer; - private Text filterTxt; - private String filterHelpMsg = "Type filter criterion " - + "separated by a space"; - - private Font italic; - private Font bold; - - /** Overwrite to display other columns */ - public List getColumnsDef() { - List columnDefs = new ArrayList(); - - // User ID - columnDefs.add(new JcrColumnDefinition(ARGEO_USER_ID, - PropertyType.STRING, "User ID", 100)); - // Displayed name - columnDefs.add(new JcrColumnDefinition(Property.JCR_TITLE, - PropertyType.STRING, "Name", 150)); - - // E-mail - columnDefs.add(new JcrColumnDefinition(ARGEO_PRIMARY_EMAIL, - PropertyType.STRING, "E-mail", 150)); - - // Description - columnDefs.add(new JcrColumnDefinition(Property.JCR_DESCRIPTION, - PropertyType.STRING, "Description", 200)); - - return columnDefs; - } - - public JcrUsersTable(Composite parent, int style, Session session) { - super(parent, SWT.NO_FOCUS); - this.tableStyle = style; - this.session = session; - } - - /** - * - * @param addFilter - * choose to add a field to filter results or not - * @param addSelection - * choose to add a column to select some of the displayed results - * or not - */ - public void populate(boolean addFilter, boolean addSelection) { - // initialization - Composite parent = this; - italic = EclipseUiUtils.getItalicFont(parent); - bold = EclipseUiUtils.getBoldFont(parent); - hasFilter = addFilter; - hasSelectionColumn = addSelection; - - // Main Layout - GridLayout layout = EclipseUiUtils.noSpaceGridLayout(); - layout.verticalSpacing = 5; - this.setLayout(layout); - if (hasFilter) - createFilterPart(parent); - usersViewer = createTableViewer(parent); - // EclipseUiSpecificUtils.enableToolTipSupport(usersViewer); - usersViewer.setContentProvider(new UsersContentProvider()); - refreshFilteredList(); - } - - public List getSelectedUsers() { - if (hasSelectionColumn) { - Object[] elements = ((CheckboxTableViewer) usersViewer) - .getCheckedElements(); - - List result = new ArrayList(); - for (Object obj : elements) { - result.add((Node) obj); - } - return result; - } else - throw new EclipseUiException("Unvalid request: no selection column " - + "has been created for the current table"); - } - - /** Returns the User table viewer, typically to add doubleclick listener */ - public TableViewer getTableViewer() { - return usersViewer; - } - - /** Returns filter String or null */ - protected String getFilterString() { - return hasFilter ? filterTxt.getText() : null; - } - - private TableViewer createTableViewer(final Composite parent) { - int style = tableStyle | SWT.H_SCROLL | SWT.V_SCROLL; - if (hasSelectionColumn) - style = style | SWT.CHECK; - - Table table = new Table(parent, style); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - TableViewer viewer; - if (hasSelectionColumn) - viewer = new CheckboxTableViewer(table); - else - viewer = new TableViewer(table); - table.setLinesVisible(true); - table.setHeaderVisible(true); - - TableViewerColumn column; - int offset = 0; - if (hasSelectionColumn) { - offset = 1; - column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, - 25); - column.setLabelProvider(new ColumnLabelProvider() { - private static final long serialVersionUID = 1L; - - @Override - public String getText(Object element) { - return null; - } - }); - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = 1L; - - boolean allSelected = false; - - @Override - public void widgetSelected(SelectionEvent e) { - allSelected = !allSelected; - ((CheckboxTableViewer) usersViewer) - .setAllChecked(allSelected); - } - }; - column.getColumn().addSelectionListener(selectionAdapter); - } - - // Create other columns - List colDefs = getColumnsDef(); - - NodeViewerComparator comparator = new NodeViewerComparator(); - int i = offset; - for (JcrColumnDefinition colDef : colDefs) { - column = ViewerUtils.createTableViewerColumn(viewer, - colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize()); - column.setLabelProvider(new CLProvider(colDef.getPropertyName())); - column.getColumn().addSelectionListener( - JcrUiUtils.getNodeSelectionAdapter(i, - colDef.getPropertyType(), colDef.getPropertyName(), - comparator, viewer)); - i++; - } - - // IMPORTANT: initialize comparator before setting it - JcrColumnDefinition firstCol = colDefs.get(0); - comparator.setColumn(firstCol.getPropertyType(), - firstCol.getPropertyName()); - viewer.setComparator(comparator); - - return viewer; - } - - private class CLProvider extends SimpleJcrNodeLabelProvider { - - private static final long serialVersionUID = 1L; - - public CLProvider(String propertyName) { - super(propertyName); - } - - public String getToolTipText(Object element) { - return getText(element); - } - - @Override - public Font getFont(Object elem) { - // self - String username = getProperty(elem, ARGEO_USER_ID); - if (username.equals(session.getUserID())) - return bold; - // disabled - try { - Node userProfile = (Node) elem; - if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) - return italic; - else - return null; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get font for " + username, e); - } - } - } - - @Override - public boolean setFocus() { - usersViewer.getTable().setFocus(); - return true; - } - - @Override - public void dispose() { - super.dispose(); - } - - public void refresh() { - refreshFilteredList(); - } - - private String getProperty(Object element, String name) { - try { - Node userProfile = (Node) element; - return userProfile.hasProperty(name) ? userProfile - .getProperty(name).getString() : ""; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get property " + name, e); - } - } - - private class UsersContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 1L; - - public Object[] getElements(Object inputElement) { - return (Object[]) inputElement; - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - } - - /* MANAGE FILTER */ - private void createFilterPart(Composite parent) { - // Text Area for the filter - filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH - | SWT.ICON_CANCEL); - filterTxt.setMessage(filterHelpMsg); - filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL - | GridData.HORIZONTAL_ALIGN_FILL)); - filterTxt.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = 1L; - - public void modifyText(ModifyEvent event) { - refreshFilteredList(); - } - }); - } - - /** - * Refresh the user list: caller might overwrite in order to display a - * subset of all users, typically to remove current user from the list - */ - protected void refreshFilteredList() { - List nodes; - try { - nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session, - hasFilter ? filterTxt.getText() : null)); - usersViewer.setInput(nodes.toArray()); - } catch (RepositoryException e) { - throw new EclipseUiException("Unable to list users", e); - } - } - - /** - * Build repository request : caller might overwrite in order to display a - * subset of all users - */ - protected NodeIterator listFilteredElements(Session session, String filter) - throws RepositoryException { - QueryManager queryManager = session.getWorkspace().getQueryManager(); - QueryObjectModelFactory factory = queryManager.getQOMFactory(); - - Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE, - ArgeoTypes.ARGEO_USER_PROFILE); - - // Dynamically build constraint depending on the filter String - Constraint defaultC = null; - if (filter != null && !"".equals(filter.trim())) { - String[] strs = filter.trim().split(" "); - for (String token : strs) { - StaticOperand so = factory.literal(session.getValueFactory() - .createValue("*" + token + "*")); - Constraint currC = factory.fullTextSearch( - source.getSelectorName(), null, so); - if (defaultC == null) - defaultC = currC; - else - defaultC = factory.and(defaultC, currC); - } - } - - Ordering order = factory.ascending(factory.propertyValue( - source.getSelectorName(), ARGEO_USER_ID)); - Ordering[] orderings = { order }; - - QueryObjectModel query = factory.createQuery(source, defaultC, - orderings, null); - - QueryResult result = query.execute(); - return result.getNodes(); - } -} \ No newline at end of file +// public class JcrUsersTable extends Composite implements ArgeoNames { +// // private final static Log log = +// // LogFactory.getLog(UserTableComposite.class); +// +// private static final long serialVersionUID = -7385959046279360420L; +// +// private Session session; +// +// private boolean hasFilter; +// private boolean hasSelectionColumn; +// private int tableStyle; +// +// private TableViewer usersViewer; +// private Text filterTxt; +// private String filterHelpMsg = "Type filter criterion " +// + "separated by a space"; +// +// private Font italic; +// private Font bold; +// +// /** Overwrite to display other columns */ +// public List getColumnsDef() { +// List columnDefs = new ArrayList(); +// +// // User ID +// columnDefs.add(new JcrColumnDefinition(ARGEO_USER_ID, +// PropertyType.STRING, "User ID", 100)); +// // Displayed name +// columnDefs.add(new JcrColumnDefinition(Property.JCR_TITLE, +// PropertyType.STRING, "Name", 150)); +// +// // E-mail +// columnDefs.add(new JcrColumnDefinition(ARGEO_PRIMARY_EMAIL, +// PropertyType.STRING, "E-mail", 150)); +// +// // Description +// columnDefs.add(new JcrColumnDefinition(Property.JCR_DESCRIPTION, +// PropertyType.STRING, "Description", 200)); +// +// return columnDefs; +// } +// +// public JcrUsersTable(Composite parent, int style, Session session) { +// super(parent, SWT.NO_FOCUS); +// this.tableStyle = style; +// this.session = session; +// } +// +// /** +// * +// * @param addFilter +// * choose to add a field to filter results or not +// * @param addSelection +// * choose to add a column to select some of the displayed results +// * or not +// */ +// public void populate(boolean addFilter, boolean addSelection) { +// // initialization +// Composite parent = this; +// italic = EclipseUiUtils.getItalicFont(parent); +// bold = EclipseUiUtils.getBoldFont(parent); +// hasFilter = addFilter; +// hasSelectionColumn = addSelection; +// +// // Main Layout +// GridLayout layout = EclipseUiUtils.noSpaceGridLayout(); +// layout.verticalSpacing = 5; +// this.setLayout(layout); +// if (hasFilter) +// createFilterPart(parent); +// usersViewer = createTableViewer(parent); +// // EclipseUiSpecificUtils.enableToolTipSupport(usersViewer); +// usersViewer.setContentProvider(new UsersContentProvider()); +// refreshFilteredList(); +// } +// +// public List getSelectedUsers() { +// if (hasSelectionColumn) { +// Object[] elements = ((CheckboxTableViewer) usersViewer) +// .getCheckedElements(); +// +// List result = new ArrayList(); +// for (Object obj : elements) { +// result.add((Node) obj); +// } +// return result; +// } else +// throw new EclipseUiException("Unvalid request: no selection column " +// + "has been created for the current table"); +// } +// +// /** Returns the User table viewer, typically to add doubleclick listener */ +// public TableViewer getTableViewer() { +// return usersViewer; +// } +// +// /** Returns filter String or null */ +// protected String getFilterString() { +// return hasFilter ? filterTxt.getText() : null; +// } +// +// private TableViewer createTableViewer(final Composite parent) { +// int style = tableStyle | SWT.H_SCROLL | SWT.V_SCROLL; +// if (hasSelectionColumn) +// style = style | SWT.CHECK; +// +// Table table = new Table(parent, style); +// table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); +// +// TableViewer viewer; +// if (hasSelectionColumn) +// viewer = new CheckboxTableViewer(table); +// else +// viewer = new TableViewer(table); +// table.setLinesVisible(true); +// table.setHeaderVisible(true); +// +// TableViewerColumn column; +// int offset = 0; +// if (hasSelectionColumn) { +// offset = 1; +// column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, +// 25); +// column.setLabelProvider(new ColumnLabelProvider() { +// private static final long serialVersionUID = 1L; +// +// @Override +// public String getText(Object element) { +// return null; +// } +// }); +// SelectionAdapter selectionAdapter = new SelectionAdapter() { +// private static final long serialVersionUID = 1L; +// +// boolean allSelected = false; +// +// @Override +// public void widgetSelected(SelectionEvent e) { +// allSelected = !allSelected; +// ((CheckboxTableViewer) usersViewer) +// .setAllChecked(allSelected); +// } +// }; +// column.getColumn().addSelectionListener(selectionAdapter); +// } +// +// // Create other columns +// List colDefs = getColumnsDef(); +// +// NodeViewerComparator comparator = new NodeViewerComparator(); +// int i = offset; +// for (JcrColumnDefinition colDef : colDefs) { +// column = ViewerUtils.createTableViewerColumn(viewer, +// colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize()); +// column.setLabelProvider(new CLProvider(colDef.getPropertyName())); +// column.getColumn().addSelectionListener( +// JcrUiUtils.getNodeSelectionAdapter(i, +// colDef.getPropertyType(), colDef.getPropertyName(), +// comparator, viewer)); +// i++; +// } +// +// // IMPORTANT: initialize comparator before setting it +// JcrColumnDefinition firstCol = colDefs.get(0); +// comparator.setColumn(firstCol.getPropertyType(), +// firstCol.getPropertyName()); +// viewer.setComparator(comparator); +// +// return viewer; +// } +// +// private class CLProvider extends SimpleJcrNodeLabelProvider { +// +// private static final long serialVersionUID = 1L; +// +// public CLProvider(String propertyName) { +// super(propertyName); +// } +// +// public String getToolTipText(Object element) { +// return getText(element); +// } +// +// // @Override +// // public Font getFont(Object elem) { +// // // self +// // String username = getProperty(elem, ARGEO_USER_ID); +// // if (username.equals(session.getUserID())) +// // return bold; +// // // disabled +// // try { +// // Node userProfile = (Node) elem; +// // if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) +// // return italic; +// // else +// // return null; +// // } catch (RepositoryException e) { +// // throw new EclipseUiException("Cannot get font for " + username, e); +// // } +// // } +// } +// +// @Override +// public boolean setFocus() { +// usersViewer.getTable().setFocus(); +// return true; +// } +// +// @Override +// public void dispose() { +// super.dispose(); +// } +// +// public void refresh() { +// refreshFilteredList(); +// } +// +// private String getProperty(Object element, String name) { +// try { +// Node userProfile = (Node) element; +// return userProfile.hasProperty(name) ? userProfile +// .getProperty(name).getString() : ""; +// } catch (RepositoryException e) { +// throw new EclipseUiException("Cannot get property " + name, e); +// } +// } +// +// private class UsersContentProvider implements IStructuredContentProvider { +// private static final long serialVersionUID = 1L; +// +// public Object[] getElements(Object inputElement) { +// return (Object[]) inputElement; +// } +// +// public void dispose() { +// } +// +// public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { +// } +// } +// +// /* MANAGE FILTER */ +// private void createFilterPart(Composite parent) { +// // Text Area for the filter +// filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH +// | SWT.ICON_CANCEL); +// filterTxt.setMessage(filterHelpMsg); +// filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL +// | GridData.HORIZONTAL_ALIGN_FILL)); +// filterTxt.addModifyListener(new ModifyListener() { +// private static final long serialVersionUID = 1L; +// +// public void modifyText(ModifyEvent event) { +// refreshFilteredList(); +// } +// }); +// } +// +// /** +// * Refresh the user list: caller might overwrite in order to display a +// * subset of all users, typically to remove current user from the list +// */ +// protected void refreshFilteredList() { +// List nodes; +// try { +// nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session, +// hasFilter ? filterTxt.getText() : null)); +// usersViewer.setInput(nodes.toArray()); +// } catch (RepositoryException e) { +// throw new EclipseUiException("Unable to list users", e); +// } +// } +// +// /** +// * Build repository request : caller might overwrite in order to display a +// * subset of all users +// */ +// protected NodeIterator listFilteredElements(Session session, String filter) +// throws RepositoryException { +// QueryManager queryManager = session.getWorkspace().getQueryManager(); +// QueryObjectModelFactory factory = queryManager.getQOMFactory(); +// +// Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE, +// ArgeoTypes.ARGEO_USER_PROFILE); +// +// // Dynamically build constraint depending on the filter String +// Constraint defaultC = null; +// if (filter != null && !"".equals(filter.trim())) { +// String[] strs = filter.trim().split(" "); +// for (String token : strs) { +// StaticOperand so = factory.literal(session.getValueFactory() +// .createValue("*" + token + "*")); +// Constraint currC = factory.fullTextSearch( +// source.getSelectorName(), null, so); +// if (defaultC == null) +// defaultC = currC; +// else +// defaultC = factory.and(defaultC, currC); +// } +// } +// +// Ordering order = factory.ascending(factory.propertyValue( +// source.getSelectorName(), ARGEO_USER_ID)); +// Ordering[] orderings = { order }; +// +// QueryObjectModel query = factory.createQuery(source, defaultC, +// orderings, null); +// +// QueryResult result = query.execute(); +// return result.getNodes(); +// } +// } \ No newline at end of file diff --git a/org.argeo.jcr/ext/test/org/argeo/jcr/tabular/JcrTabularTest.java b/org.argeo.jcr/ext/test/org/argeo/jcr/tabular/JcrTabularTest.java deleted file mode 100644 index 8896b2f4b..000000000 --- a/org.argeo.jcr/ext/test/org/argeo/jcr/tabular/JcrTabularTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.tabular; - -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.PropertyType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.argeo.jackrabbit.unit.AbstractJackrabbitTestCase; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularRow; -import org.argeo.util.tabular.TabularRowIterator; -import org.argeo.util.tabular.TabularWriter; - -public class JcrTabularTest extends AbstractJackrabbitTestCase { - private final static Log log = LogFactory.getLog(JcrTabularTest.class); - - public void testWriteReadCsv() throws Exception { - session().setNamespacePrefix("argeo", ArgeoNames.ARGEO_NAMESPACE); - InputStreamReader reader = new InputStreamReader(getClass() - .getResourceAsStream("/org/argeo/jcr/argeo.cnd")); - CndImporter.registerNodeTypes(reader, session()); - reader.close(); - - // write - Integer columnCount = 15; - Long rowCount = 1000l; - String stringValue = "test, \ntest"; - - List header = new ArrayList(); - for (int i = 0; i < columnCount; i++) { - header.add(new TabularColumn("col" + i, PropertyType.STRING)); - } - Node tableNode = session().getRootNode().addNode("table", - ArgeoTypes.ARGEO_TABLE); - TabularWriter writer = new JcrTabularWriter(tableNode, header, - ArgeoTypes.ARGEO_CSV); - for (int i = 0; i < rowCount; i++) { - List objs = new ArrayList(); - for (int j = 0; j < columnCount; j++) { - objs.add(stringValue); - } - writer.appendRow(objs.toArray()); - } - writer.close(); - session().save(); - - if (log.isDebugEnabled()) - log.debug("Wrote tabular content " + rowCount + " rows, " - + columnCount + " columns"); - // read - TabularRowIterator rowIt = new JcrTabularRowIterator(tableNode); - Long count = 0l; - while (rowIt.hasNext()) { - TabularRow tr = rowIt.next(); - assertEquals(header.size(), tr.size()); - count++; - } - assertEquals(rowCount, count); - if (log.isDebugEnabled()) - log.debug("Read tabular content " + rowCount + " rows, " - + columnCount + " columns"); - } -} diff --git a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitContainer.java b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitContainer.java deleted file mode 100644 index c5ca7952c..000000000 --- a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitContainer.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.jackrabbit; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -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.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; -import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.JcrUtils; -import org.springframework.core.io.Resource; -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}. - */ -@Deprecated -public class JackrabbitContainer extends JackrabbitWrapper { - private final static Log log = LogFactory.getLog(JackrabbitContainer.class); - - // local - private Resource configuration; - - private Resource variables; - - private RepositoryConfig repositoryConfig; - private File homeDirectory; - private Boolean inMemory = false; - - /** Migrations to execute (if not already done) */ - private Set dataModelMigrations = new HashSet(); - - /** Straight (non spring) values */ - private Properties configurationProperties; - private InputSource configurationXml; - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public JackrabbitContainer() { - } - - public void init() { - // long begin = System.currentTimeMillis(); - - if (getRepository() != null) - throw new ArgeoJcrException("Cannot be used to wrap another repository"); - Repository repository = createJackrabbitRepository(); - super.setRepository(repository); - - // migrate if needed - migrate(); - - // apply new CND files after migration - prepareDataModel(); - - // double duration = ((double) (System.currentTimeMillis() - begin)) / - // 1000; - // if (log.isDebugEnabled()) - // log.debug("Initialized JCR repository wrapper in " + duration - // + " s"); - } - - /** Actually creates the new repository. */ - protected Repository createJackrabbitRepository() { - long begin = System.currentTimeMillis(); - InputStream configurationIn = null; - Repository repository; - try { - // temporary - if (inMemory && getHomeDirectory().exists()) { - FileUtils.deleteDirectory(getHomeDirectory()); - log.warn("Deleted Jackrabbit home directory " + getHomeDirectory()); - } - - // process configuration file - Properties vars = getConfigurationProperties(); - vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, getHomeDirectory().getCanonicalPath()); - InputSource is; - if (configurationXml != null) - is = configurationXml; - else { - configurationIn = readConfiguration(); - is = new InputSource(configurationIn); - } - repositoryConfig = RepositoryConfig.create(is, 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) { - throw new ArgeoJcrException("Cannot create Jackrabbit repository " + getHomeDirectory(), 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 ArgeoJcrException("Cannot get canonical file for " + homeDirectory, e); - } - } - - /** Executes migrations, if needed. */ - protected void migrate() { - // No migration to perform - if (dataModelMigrations.size() == 0) - return; - - Boolean restartAndClearCaches = false; - - // migrate data - Session session = null; - try { - session = login(); - for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( - dataModelMigrations)) { - if (dataModelMigration.migrate(session)) { - restartAndClearCaches = true; - } - } - } catch (ArgeoJcrException e) { - throw e; - } catch (Exception e) { - throw new ArgeoJcrException("Cannot migrate", e); - } finally { - JcrUtils.logoutQuietly(session); - } - - // restart repository - if (restartAndClearCaches) { - Repository repository = getRepository(); - if (repository instanceof RepositoryImpl) { - JackrabbitDataModelMigration.clearRepositoryCaches(((RepositoryImpl) repository).getConfig()); - } - ((JackrabbitRepository) repository).shutdown(); - createJackrabbitRepository(); - } - - // set data model version - try { - session = login(); - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot login to migrated repository", e); - } - - for (JackrabbitDataModelMigration dataModelMigration : new TreeSet( - dataModelMigrations)) { - try { - if (session.itemExists(dataModelMigration.getDataModelNodePath())) { - Node dataModelNode = session.getNode(dataModelMigration.getDataModelNodePath()); - dataModelNode.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, - dataModelMigration.getTargetVersion()); - session.save(); - } - } catch (Exception e) { - log.error("Cannot set model version", e); - } - } - JcrUtils.logoutQuietly(session); - - } - - /** 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; - if (log.isTraceEnabled()) - log.trace("Destroyed Jackrabbit repository in " + duration + " s, home: " + getHomeDirectory()); - } - repository = null; - } - - public void dispose() { - throw new IllegalArgumentException("Call destroy() method instead of dispose()"); - } - - /* - * UTILITIES - */ - /** - * Reads the configuration which will initialize a {@link RepositoryConfig}. - */ - protected InputStream readConfiguration() { - try { - return configuration != null ? configuration.getInputStream() : null; - } catch (IOException e) { - throw new ArgeoJcrException("Cannot read Jackrabbit configuration " + configuration, e); - } - } - - /** - * 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; - } catch (IOException e) { - throw new ArgeoJcrException("Cannot read Jackrabbit variables " + variables, e); - } - } - - /** - * Resolves ${} placeholders in the provided string. Based on system - * properties if no map is provided. - */ - protected String resolvePlaceholders(String string, Map variables) { - return SystemPropertyUtils.resolvePlaceholders(string); - } - - /** Generates the properties to use in the configuration. */ - protected Properties getConfigurationProperties() { - if (configurationProperties != null) - return configurationProperties; - - 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(vars.keySet())) - log.trace(key + "=" + vars.getProperty(key.toString())); - } - - } catch (IOException e) { - throw new ArgeoJcrException("Cannot read configuration properties", e); - } finally { - IOUtils.closeQuietly(propsIn); - } - return vars; - } - - /* - * FIELDS ACCESS - */ - - public void setHomeDirectory(File homeDirectory) { - this.homeDirectory = homeDirectory; - } - - public void setInMemory(Boolean inMemory) { - this.inMemory = inMemory; - } - - public void setRepository(Repository repository) { - throw new ArgeoJcrException("Cannot be used to wrap another repository"); - } - - public void setDataModelMigrations(Set dataModelMigrations) { - this.dataModelMigrations = dataModelMigrations; - } - - public void setVariables(Resource variables) { - this.variables = variables; - } - - public void setConfiguration(Resource configuration) { - this.configuration = configuration; - } - - public void setConfigurationProperties(Properties configurationProperties) { - this.configurationProperties = configurationProperties; - } - - public void setConfigurationXml(InputSource configurationXml) { - this.configurationXml = configurationXml; - } - -} diff --git a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java index 53f0e4457..e53ed5577 100644 --- a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java +++ b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java @@ -27,12 +27,12 @@ import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.commons.cnd.CndImporter; import org.apache.jackrabbit.core.config.RepositoryConfig; import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.JcrCallback; import org.argeo.jcr.JcrUtils; import org.springframework.core.io.Resource; /** Migrate the data in a Jackrabbit repository. */ +@Deprecated public class JackrabbitDataModelMigration implements Comparable { private final static Log log = LogFactory @@ -61,15 +61,15 @@ public class JackrabbitDataModelMigration implements return false; } Node dataModelNode = session.getNode(dataModelNodePath); - if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) { - String currentVersion = dataModelNode.getProperty( - ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); - if (compareVersions(currentVersion, targetVersion) >= 0) { - log.info("Data model at version " + currentVersion - + ", no need to migrate."); - return false; - } - } +// if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) { +// String currentVersion = dataModelNode.getProperty( +// ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); +// if (compareVersions(currentVersion, targetVersion) >= 0) { +// log.info("Data model at version " + currentVersion +// + ", no need to migrate."); +// return false; +// } +// } // apply transitional CND if (migrationCnd != null) { diff --git a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java index e4134883c..f7e882e7b 100644 --- a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java +++ b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java @@ -36,7 +36,6 @@ 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.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.ArgeoJcrException; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -46,10 +45,19 @@ import org.xml.sax.InputSource; * Repository factory which can create new repositories and access remote * Jackrabbit repositories */ -public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrConstants { - private final static Log log = LogFactory.getLog(JackrabbitRepositoryFactory.class); +@Deprecated +public class JackrabbitRepositoryFactory implements RepositoryFactory { + // FIXME factorize with node + /** Key for a JCR repository alias */ + public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; + /** Key for a JCR repository URI */ + public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; - private Resource fileRepositoryConfiguration = new ClassPathResource("/org/argeo/jackrabbit/repository-h2.xml"); + private final static Log log = LogFactory + .getLog(JackrabbitRepositoryFactory.class); + + private Resource fileRepositoryConfiguration = new ClassPathResource( + "/org/argeo/jackrabbit/repository-h2.xml"); @SuppressWarnings({ "rawtypes" }) public Repository getRepository(Map parameters) throws RepositoryException { @@ -72,7 +80,9 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC else if (uri.startsWith("file"))// http, https repository = createFileRepository(uri, parameters); else if (uri.startsWith("vm")) { - log.warn("URI " + uri + " should have been managed by generic JCR repository factory"); + log.warn("URI " + + uri + + " should have been managed by generic JCR repository factory"); repository = getRepositoryByAlias(getAliasFromURI(uri)); } else throw new ArgeoJcrException("Unrecognized URI format " + uri); @@ -88,7 +98,8 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC // with properties " + properties); repository = getRepositoryByAlias(alias); } else - throw new ArgeoJcrException("Not enough information in " + parameters); + throw new ArgeoJcrException("Not enough information in " + + parameters); if (repository == null) throw new ArgeoJcrException("Repository not found " + parameters); @@ -100,18 +111,22 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC return null; } - protected Repository createRemoteRepository(String uri) throws RepositoryException { + protected Repository createRemoteRepository(String uri) + throws RepositoryException { Map params = new HashMap(); params.put(JcrUtils.REPOSITORY_URI, uri); - Repository repository = new Jcr2davRepositoryFactory().getRepository(params); + Repository repository = new Jcr2davRepositoryFactory() + .getRepository(params); if (repository == null) - throw new ArgeoJcrException("Remote Davex repository " + uri + " not found"); + throw new ArgeoJcrException("Remote Davex repository " + uri + + " not found"); log.info("Initialized remote Jackrabbit repository from uri " + uri); return repository; } @SuppressWarnings({ "rawtypes", "unchecked" }) - protected Repository createFileRepository(final String uri, Map parameters) throws RepositoryException { + protected Repository createFileRepository(final String uri, Map parameters) + throws RepositoryException { InputStream configurationIn = null; try { Properties vars = new Properties(); @@ -119,26 +134,32 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC String dirPath = uri.substring("file:".length()); File homeDir = new File(dirPath); if (homeDir.exists() && !homeDir.isDirectory()) - throw new ArgeoJcrException("Repository home " + dirPath + " is not a directory"); + throw new ArgeoJcrException("Repository home " + dirPath + + " is not a directory"); if (!homeDir.exists()) homeDir.mkdirs(); configurationIn = fileRepositoryConfiguration.getInputStream(); - vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getCanonicalPath()); - RepositoryConfig repositoryConfig = RepositoryConfig.create(new InputSource(configurationIn), vars); + vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, + homeDir.getCanonicalPath()); + RepositoryConfig repositoryConfig = RepositoryConfig.create( + new InputSource(configurationIn), vars); // TransientRepository repository = new // TransientRepository(repositoryConfig); - final RepositoryImpl repository = RepositoryImpl.create(repositoryConfig); + final RepositoryImpl repository = RepositoryImpl + .create(repositoryConfig); Session session = repository.login(); // FIXME make it generic - org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN", "jcr:all"); + org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN", + "jcr:all"); org.argeo.jcr.JcrUtils.logoutQuietly(session); - Runtime.getRuntime().addShutdownHook(new Thread("Clean JCR repository " + uri) { - public void run() { - repository.shutdown(); - log.info("Destroyed repository " + uri); - } - }); + Runtime.getRuntime().addShutdownHook( + new Thread("Clean JCR repository " + uri) { + public void run() { + repository.shutdown(); + log.info("Destroyed repository " + uri); + } + }); log.info("Initialized file Jackrabbit repository from uri " + uri); return repository; } catch (Exception e) { @@ -171,7 +192,8 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC } - public void setFileRepositoryConfiguration(Resource fileRepositoryConfiguration) { + public void setFileRepositoryConfiguration( + Resource fileRepositoryConfiguration) { this.fileRepositoryConfiguration = fileRepositoryConfiguration; } diff --git a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java b/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java deleted file mode 100644 index 268ecdb28..000000000 --- a/org.argeo.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.jackrabbit; - -import java.io.ByteArrayInputStream; -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 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.nodetype.NodeType; - -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.api.JackrabbitRepository; -import org.apache.jackrabbit.commons.NamespaceHelper; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrRepositoryWrapper; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.security.DigestUtils; -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}. - */ -@Deprecated -public class JackrabbitWrapper extends JcrRepositoryWrapper implements - JackrabbitRepository, ResourceLoaderAware { - private final static Log log = LogFactory.getLog(JackrabbitWrapper.class); - private final static String DIGEST_ALGORITHM = "MD5"; - - // local - private ResourceLoader resourceLoader; - - // data model - /** Node type definitions in CND format */ - private List cndFiles = new ArrayList(); - /** - * Always import CNDs. Useful during development of new data models. In - * production, explicit migration processes should be used. - */ - private Boolean forceCndImport = true; - - /** Namespaces to register: key is prefix, value namespace */ - private Map namespaces = new HashMap(); - - private BundleContext bundleContext; - - /** - * Explicitly set admin credentials used in initialization. Useful for - * testing, in real applications authentication is rather dealt with - * externally - */ - private Credentials adminCredentials = null; - - /** - * Empty constructor, {@link #init()} should be called after properties have - * been set - */ - public JackrabbitWrapper() { - } - - @Override - public void init() { - prepareDataModel(); - } - - /* - * DATA MODEL - */ - - /** - * 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() { - if ((cndFiles == null || cndFiles.size() == 0) - && (namespaces == null || namespaces.size() == 0)) - return; - - Session session = null; - try { - session = login(adminCredentials); - // 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) { - processCndFile(session, resUrl); - } - } catch (Exception e) { - JcrUtils.discardQuietly(session); - throw new ArgeoJcrException("Cannot import node type definitions " - + cndFiles, e); - } finally { - JcrUtils.logoutQuietly(session); - } - - } - - protected void processCndFile(Session session, String resUrl) { - Reader reader = null; - try { - // 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; - } - } - - byte[] cndContent = readCndContent(resUrl); - String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent); - Bundle bundle = findDataModelBundle(resUrl); - - String currentVersion = null; - if (dataModel != null) { - currentVersion = dataModel.getProperty( - ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); - if (dataModel.hasNode(Node.JCR_CONTENT)) { - String oldDigest = JcrUtils.checksumFile(dataModel, - DIGEST_ALGORITHM); - if (oldDigest.equals(newDigest)) { - if (log.isTraceEnabled()) - log.trace("Data model " + resUrl - + " hasn't changed, keeping version " - + currentVersion); - return; - } - } - } - - if (dataModel != null && !forceCndImport) { - log.info("Data model " - + resUrl - + " has changed since version " - + currentVersion - + (bundle != null ? ": version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - return; - } - - reader = new InputStreamReader(new ByteArrayInputStream(cndContent)); - // actually imports the CND - try { - CndImporter.registerNodeTypes(reader, session, true); - } catch (Exception e) { - log.error("Cannot import data model " + resUrl, e); - return; - } - - if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) { - dataModel.remove(); - dataModel = null; - } - - // 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(resUrl); - if (dataModel == null) { - dataModel = dataModels.addNode(fileName, NodeType.NT_FILE); - dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE); - dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL); - dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl); - } else { - session.getWorkspace().getVersionManager() - .checkout(dataModel.getPath()); - } - if (bundle != null) - dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, - bundle.getVersion().toString()); - else - dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, - "0.0.0"); - JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName, - cndContent); - JcrUtils.updateLastModified(dataModel); - session.save(); - session.getWorkspace().getVersionManager() - .checkin(dataModel.getPath()); - - if (currentVersion == null) - log.info("Data model " - + resUrl - + (bundle != null ? ", version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - else - log.info("Data model " - + resUrl - + " updated from version " - + currentVersion - + (bundle != null ? ", version " + bundle.getVersion() - + ", bundle " + bundle.getSymbolicName() : "")); - } catch (Exception e) { - throw new ArgeoJcrException("Cannot process data model " + resUrl, e); - } finally { - IOUtils.closeQuietly(reader); - } - } - - protected byte[] readCndContent(String resUrl) { - InputStream in = null; - try { - boolean classpath; - // normalize URL - if (bundleContext != null && 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 '/'"); - } - classpath = true; - } else { - classpath = false; - } - - URL url = null; - if (classpath) { - if (bundleContext != null) { - Bundle currentBundle = bundleContext.getBundle(); - url = currentBundle.getResource(resUrl); - } else { - resUrl = "classpath:" + resUrl; - url = null; - } - } else if (!resUrl.startsWith("classpath:")) { - url = new URL(resUrl); - } - - if (url != null) { - in = url.openStream(); - } else if (resourceLoader != null) { - Resource res = resourceLoader.getResource(resUrl); - in = res.getInputStream(); - url = res.getURL(); - } else { - throw new ArgeoJcrException("No " + resUrl + " in the classpath," - + " make sure the containing" + " package is visible."); - } - - return IOUtils.toByteArray(in); - } catch (Exception e) { - throw new ArgeoJcrException("Cannot read CND from " + resUrl, e); - } finally { - IOUtils.closeQuietly(in); - } - } - - /* - * JACKRABBIT REPOSITORY IMPLEMENTATION - */ - @Override - public Session login(Credentials credentials, String workspaceName, - Map attributes) throws LoginException, - NoSuchWorkspaceException, RepositoryException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void shutdown() { - // TODO Auto-generated method stub - - } - - /* - * UTILITIES - */ - /** Find which OSGi bundle provided the data model resource */ - protected Bundle findDataModelBundle(String resUrl) { - if (bundleContext == null) - return null; - - if (resUrl.startsWith("/")) - resUrl = resUrl.substring(1); - String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/', - '.'); - ServiceReference paSr = bundleContext - .getServiceReference(PackageAdmin.class); - PackageAdmin packageAdmin = (PackageAdmin) bundleContext - .getService(paSr); - - // find exported package - ExportedPackage exportedPackage = null; - ExportedPackage[] exportedPackages = packageAdmin - .getExportedPackages(pkg); - if (exportedPackages == null) - throw new ArgeoJcrException("No exported package found for " + pkg); - for (ExportedPackage ep : exportedPackages) { - for (Bundle b : ep.getImportingBundles()) { - if (b.getBundleId() == bundleContext.getBundle().getBundleId()) { - exportedPackage = ep; - break; - } - } - } - - Bundle exportingBundle = null; - if (exportedPackage != null) { - exportingBundle = exportedPackage.getExportingBundle(); - } else { - // assume this is in the same bundle - exportingBundle = bundleContext.getBundle(); - // throw new ArgeoJcrException("No OSGi exporting package found for " - // + resUrl); - } - return exportingBundle; - } - - /* - * FIELDS ACCESS - */ - public void setNamespaces(Map namespaces) { - this.namespaces = namespaces; - } - - public void setCndFiles(List cndFiles) { - this.cndFiles = cndFiles; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - protected BundleContext getBundleContext() { - return bundleContext; - } - - public void setForceCndImport(Boolean forceCndUpdate) { - this.forceCndImport = forceCndUpdate; - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - public void setAdminCredentials(Credentials adminCredentials) { - this.adminCredentials = adminCredentials; - } - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrConstants.java b/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrConstants.java deleted file mode 100644 index 26979e927..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrConstants.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.Repository; - -/** Argeo model specific constants */ -public interface ArgeoJcrConstants { - public final static String ARGEO_BASE_PATH = "/argeo:system"; - public final static String DATA_MODELS_BASE_PATH = ARGEO_BASE_PATH + "/argeo:dataModels"; - public final static String PEOPLE_BASE_PATH = ARGEO_BASE_PATH + "/argeo:people"; - - // parameters (typically for call to a RepositoryFactory) - /** Key for a JCR repository alias */ - public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; - /** Key for a JCR repository URI */ - public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; - - // standard aliases - /** - * Reserved alias for the "node" {@link Repository}, that is, the default - * JCR repository. - */ - public final static String ALIAS_NODE = "node"; - public final static String ALIAS_HOME = "home"; - public final static String BASE_REPO_PID = "argeo.repo."; - public final static String REPO_PID_NODE = BASE_REPO_PID + ALIAS_NODE; - public final static String JACKRABBIT_REPO_FACTORY_PID = "argeo.repo.factory.jackrabbit"; - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrUtils.java b/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrUtils.java deleted file mode 100644 index 9a0fd1971..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/ArgeoJcrUtils.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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 java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -/** Utilities related to Argeo model in JCR */ -public class ArgeoJcrUtils implements ArgeoJcrConstants { - /** - * Wraps the call to the repository factory based on parameter - * {@link ArgeoJcrConstants#JCR_REPOSITORY_ALIAS} in order to simplify it - * and protect against future API changes. - */ - public static Repository getRepositoryByAlias( - RepositoryFactory repositoryFactory, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_ALIAS, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoJcrException( - "Unexpected exception when trying to retrieve repository with alias " - + alias, e); - } - } - - /** - * 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) { - 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 parameters = new HashMap(); - parameters.put(JCR_REPOSITORY_URI, uri); - if (alias != null) - parameters.put(JCR_REPOSITORY_ALIAS, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new ArgeoJcrException( - "Unexpected exception when trying to retrieve repository with uri " - + uri, e); - } - } - - private ArgeoJcrUtils() { - } - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/ArgeoNames.java b/org.argeo.jcr/src/org/argeo/jcr/ArgeoNames.java deleted file mode 100644 index 1d4582a78..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/ArgeoNames.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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; - -/** JCR names in the http://www.argeo.org/argeo namespace */ -public interface ArgeoNames { - public final static String ARGEO_NAMESPACE = "http://www.argeo.org/ns/argeo"; - public final static String ARGEO = "argeo"; - - public final static String ARGEO_URI = "argeo:uri"; - public final static String ARGEO_USER_ID = "argeo:userID"; - public final static String ARGEO_PREFERENCES = "argeo:preferences"; - public final static String ARGEO_DATA_MODEL_VERSION = "argeo:dataModelVersion"; - - public final static String ARGEO_REMOTE = "argeo:remote"; - public final static String ARGEO_PASSWORD = "argeo:password"; -// public final static String ARGEO_REMOTE_ROLES = "argeo:remoteRoles"; - - // user profile - public final static String ARGEO_PROFILE = "argeo:profile"; - - // spring security - public final static String ARGEO_ENABLED = "argeo:enabled"; - public final static String ARGEO_ACCOUNT_NON_EXPIRED = "argeo:accountNonExpired"; - public final static String ARGEO_ACCOUNT_NON_LOCKED = "argeo:accountNonLocked"; - public final static String ARGEO_CREDENTIALS_NON_EXPIRED = "argeo:credentialsNonExpired"; - - // personal details - public final static String ARGEO_FIRST_NAME = "argeo:firstName"; - public final static String ARGEO_LAST_NAME = "argeo:lastName"; - public final static String ARGEO_PRIMARY_EMAIL = "argeo:primaryEmail"; - public final static String ARGEO_PRIMARY_ORGANIZATION = "argeo:primaryOrganization"; - - // tabular - public final static String ARGEO_IS_KEY = "argeo:isKey"; - - // crypto - public final static String ARGEO_IV = "argeo:iv"; - public final static String ARGEO_SECRET_KEY_FACTORY = "argeo:secretKeyFactory"; - public final static String ARGEO_SALT = "argeo:salt"; - public final static String ARGEO_ITERATION_COUNT = "argeo:iterationCount"; - public final static String ARGEO_KEY_LENGTH = "argeo:keyLength"; - public final static String ARGEO_SECRET_KEY_ENCRYPTION = "argeo:secretKeyEncryption"; - public final static String ARGEO_CIPHER = "argeo:cipher"; - public final static String ARGEO_KEYRING = "argeo:keyring"; -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/ArgeoTypes.java b/org.argeo.jcr/src/org/argeo/jcr/ArgeoTypes.java deleted file mode 100644 index a11ead53f..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/ArgeoTypes.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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; - -/** JCR types in the http://www.argeo.org/argeo namespace */ -public interface ArgeoTypes { - public final static String ARGEO_LINK = "argeo:link"; - public final static String ARGEO_USER_HOME = "argeo:userHome"; - public final static String ARGEO_USER_PROFILE = "argeo:userProfile"; - public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository"; - public final static String ARGEO_PREFERENCE_NODE = "argeo:preferenceNode"; - - // data model - public final static String ARGEO_DATA_MODEL = "argeo:dataModel"; - - // tabular - public final static String ARGEO_TABLE = "argeo:table"; - public final static String ARGEO_COLUMN = "argeo:column"; - public final static String ARGEO_CSV = "argeo:csv"; - - // crypto - public final static String ARGEO_ENCRYPTED = "argeo:encrypted"; - public final static String ARGEO_PBE_SPEC = "argeo:pbeSpec"; - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryFactory.java b/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryFactory.java deleted file mode 100644 index ccfc2698e..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryFactory.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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 java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -/** - * Simple implementation of {@link RepositoryFactory}, supporting OSGi aliases. - */ -@Deprecated -public class DefaultRepositoryFactory extends DefaultRepositoryRegister - implements RepositoryFactory, ArgeoJcrConstants { - @SuppressWarnings("rawtypes") - public Repository getRepository(Map parameters) throws RepositoryException { - if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) { - String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString(); - return getRepositoryByAlias(alias); - } else if (parameters.containsKey(JCR_REPOSITORY_URI)) { - String uri = parameters.get(JCR_REPOSITORY_URI).toString(); - return getRepositoryByAlias(getAliasFromURI(uri)); - } - return null; - } - - protected String getAliasFromURI(String uri) { - try { - URI uriObj = new URI(uri); - String alias = uriObj.getPath(); - if (alias.charAt(0) == '/') - alias = alias.substring(1); - if (alias.charAt(alias.length() - 1) == '/') - alias = alias.substring(0, alias.length() - 1); - return alias; - } catch (URISyntaxException e) { - throw new ArgeoJcrException("Cannot interpret URI " + uri, e); - } - } - - /** - * Retrieve a repository by alias - * - * @return the repository registered with alias or null if none - */ - protected Repository getRepositoryByAlias(String alias) { - if (getRepositories().containsKey(alias)) - return getRepositories().get(alias); - else - return null; - } - - protected void publish(String alias, Repository repository, - Properties properties) { - register(repository, properties); - } - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java b/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java index e2a5026d8..c9835848d 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java +++ b/org.argeo.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java @@ -28,7 +28,12 @@ import org.apache.commons.logging.LogFactory; @Deprecated public class DefaultRepositoryRegister extends Observable implements - RepositoryRegister, ArgeoJcrConstants { + RepositoryRegister { + // FIXME factorize with node + /** Key for a JCR repository alias */ + public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; + /** Key for a JCR repository URI */ + public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; private final static Log log = LogFactory .getLog(DefaultRepositoryRegister.class); diff --git a/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java b/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java index 98a2da8f3..313554041 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java +++ b/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java @@ -68,7 +68,7 @@ import org.argeo.util.security.DigestUtils; import org.argeo.util.security.SimplePrincipal; /** Utility methods to simplify common JCR operations. */ -public class JcrUtils implements ArgeoJcrConstants { +public class JcrUtils { final private static Log log = LogFactory.getLog(JcrUtils.class); diff --git a/org.argeo.jcr/src/org/argeo/jcr/UserJcrUtils.java b/org.argeo.jcr/src/org/argeo/jcr/UserJcrUtils.java deleted file mode 100644 index 95269475e..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/UserJcrUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; -import javax.jcr.query.qom.Constraint; -import javax.jcr.query.qom.DynamicOperand; -import javax.jcr.query.qom.QueryObjectModelFactory; -import javax.jcr.query.qom.Selector; -import javax.jcr.query.qom.StaticOperand; - -/** - * Utilities related to the user home and properties based on Argeo JCR model. - * Do not use anymore. Does not fit with current security model - */ -@Deprecated -public class UserJcrUtils { - /** The home base path. Not yet configurable */ - public final static String DEFAULT_HOME_BASE_PATH = "/home"; - - /** - * Returns the home node of the user or null if none was found. - * - * @param session - * the session to use in order to perform the search, this can be - * a session with a different user ID than the one searched, - * typically when a system or admin session is used. - * @param username - * the username of the user - */ - public static Node getUserHome(Session session, String username) { - try { - // String homePath = UserJcrUtils.getUserHomePath(username); - // return session.itemExists(homePath) ? session.getNode(homePath) - // : null; - // kept for example of QOM queries - QueryObjectModelFactory qomf = session.getWorkspace() - .getQueryManager().getQOMFactory(); - Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, - "userHome"); - DynamicOperand userIdDop = qomf.propertyValue( - userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); - StaticOperand userIdSop = qomf.literal(session.getValueFactory() - .createValue(username)); - Constraint constraint = qomf.comparison(userIdDop, - QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); - Query query = qomf.createQuery(userHomeSel, constraint, null, null); - return JcrUtils.querySingleNode(query); - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot find home for user " + username, e); - } - } - - public static Node getUserProfile(Session session, String username) { - try { - QueryObjectModelFactory qomf = session.getWorkspace() - .getQueryManager().getQOMFactory(); - Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_PROFILE, - "userProfile"); - DynamicOperand userIdDop = qomf.propertyValue( - userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); - StaticOperand userIdSop = qomf.literal(session.getValueFactory() - .createValue(username)); - Constraint constraint = qomf.comparison(userIdDop, - QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); - Query query = qomf.createQuery(userHomeSel, constraint, null, null); - return JcrUtils.querySingleNode(query); - } catch (RepositoryException e) { - throw new ArgeoJcrException( - "Cannot find profile for user " + username, e); - } - } - - /** Returns the home node of the session user or null if none was found. */ - public static Node getUserHome(Session session) { - String userID = session.getUserID(); - return getUserHome(session, userID); - } - - private UserJcrUtils() { - } -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/argeo.cnd b/org.argeo.jcr/src/org/argeo/jcr/argeo.cnd deleted file mode 100644 index fbfea9dd9..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/argeo.cnd +++ /dev/null @@ -1,72 +0,0 @@ - - -// GENERIC TYPES NOT AVAILABLE IN JCR -[argeo:link] > mix:created, mix:lastModified -mixin -// URI(s) -- argeo:uri (STRING) m - -[argeo:references] > nt:unstructured -- * (REFERENCE) * - -// DATA MODEL -[argeo:dataModel] > mix:created, mix:lastModified, mix:versionable -mixin -- argeo:uri (STRING) m -- argeo:dataModelVersion (STRING) m - -// USER NODES -// user should be lower case, between 3 and 15 characters long -[argeo:userHome] > mix:created, mix:lastModified -mixin -- argeo:userID (STRING) m -- argeo:remoteRoles (STRING) * -// deprecated. for backward compatibility: -+ argeo:profile (argeo:userProfile) -+ argeo:keyring (argeo:pbeSpec) -+ argeo:preferences (argeo:preferenceNode) - -[argeo:userProfile] > mix:created, mix:lastModified, mix:title, mix:versionable -mixin -- argeo:userID (STRING) m -- argeo:enabled (BOOLEAN) -- argeo:accountNonExpired (BOOLEAN) -- argeo:accountNonLocked (BOOLEAN) -- argeo:credentialsNonExpired (BOOLEAN) - -[argeo:preferenceNode] > mix:lastModified, mix:versionable -mixin -+ * (argeo:preferenceNode) * version - -[argeo:remoteRepository] > nt:unstructured -- argeo:uri (STRING) -- argeo:userID (STRING) -+ argeo:password (argeo:encrypted) - -// TABULAR CONTENT -[argeo:table] > nt:file -+ * (argeo:column) * - -[argeo:column] > mix:title -- jcr:requiredType (STRING) = 'STRING' - -[argeo:csv] > nt:resource - -// CRYPTO -[argeo:encrypted] > nt:base -mixin -// initialization vector used by some algorithms -- argeo:iv (BINARY) - -[argeo:pbeKeySpec] > nt:base -mixin -- argeo:secretKeyFactory (STRING) -- argeo:salt (BINARY) -- argeo:iterationCount (LONG) -- argeo:keyLength (LONG) -- argeo:secretKeyEncryption (STRING) - -[argeo:pbeSpec] > argeo:pbeKeySpec -mixin -- argeo:cipher (STRING) - diff --git a/org.argeo.jcr/src/org/argeo/jcr/security/JcrKeyring.java b/org.argeo.jcr/src/org/argeo/jcr/security/JcrKeyring.java deleted file mode 100644 index 8ab6ed355..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/security/JcrKeyring.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.security; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayReader; -import java.io.InputStream; -import java.io.Reader; -import java.security.Provider; -import java.security.SecureRandom; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.UserJcrUtils; -import org.argeo.util.security.AbstractKeyring; -import org.argeo.util.security.PBEKeySpecCallback; - -/** JCR based implementation of a keyring */ -public class JcrKeyring extends AbstractKeyring implements ArgeoNames { - /** - * Stronger with 256, but causes problem with Oracle JVM, force 128 in this - * case - */ - public final static Long DEFAULT_SECRETE_KEY_LENGTH = 256l; - public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; - public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; - public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; - - private Integer iterationCountFactor = 200; - private Long secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH; - private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; - private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; - private String cipherName = DEFAULT_CIPHER_NAME; - - private Session session; - - /** - * When setup is called the session has not yet been saved and we don't want - * to save it since there maybe other data which would be inconsistent. So - * we keep a reference to this node which will then be used (an reset to - * null) when handling the PBE callback. We keep one per thread in case - * multiple users are accessing the same instance of a keyring. - */ - private ThreadLocal notYetSavedKeyring = new ThreadLocal() { - - @Override - protected Node initialValue() { - return null; - } - }; - - @Override - protected Boolean isSetup() { - try { - if (notYetSavedKeyring.get() != null) - return true; - - Node userHome = UserJcrUtils.getUserHome(session); - return userHome.hasNode(ARGEO_KEYRING); - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot check whether keyring is setup", e); - } - } - - @Override - protected void setup(char[] password) { - Binary binary = null; - InputStream in = null; - try { - Node userHome = UserJcrUtils.getUserHome(session); - if (userHome.hasNode(ARGEO_KEYRING)) - throw new ArgeoJcrException("Keyring already setup"); - Node keyring = userHome.addNode(ARGEO_KEYRING); - keyring.addMixin(ArgeoTypes.ARGEO_PBE_SPEC); - - // deterministic salt and iteration count based on username - String username = session.getUserID(); - byte[] salt = new byte[8]; - byte[] usernameBytes = username.getBytes(); - for (int i = 0; i < salt.length; i++) { - if (i < usernameBytes.length) - salt[i] = usernameBytes[i]; - else - salt[i] = 0; - } - in = new ByteArrayInputStream(salt); - binary = session.getValueFactory().createBinary(in); - keyring.setProperty(ARGEO_SALT, binary); - - Integer iterationCount = username.length() * iterationCountFactor; - keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); - - // default algo - // TODO check if algo and key length are available, use DES if not - keyring.setProperty(ARGEO_SECRET_KEY_FACTORY, secreteKeyFactoryName); - keyring.setProperty(ARGEO_KEY_LENGTH, secreteKeyLength); - keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, secreteKeyEncryption); - keyring.setProperty(ARGEO_CIPHER, cipherName); - - // keyring.getSession().save(); - - // encrypted password hash - // IOUtils.closeQuietly(in); - // JcrUtils.closeQuietly(binary); - // byte[] btPass = hash(password, salt, iterationCount); - // in = new ByteArrayInputStream(btPass); - // binary = session.getValueFactory().createBinary(in); - // keyring.setProperty(ARGEO_PASSWORD, binary); - - notYetSavedKeyring.set(keyring); - } catch (Exception e) { - throw new ArgeoJcrException("Cannot setup keyring", e); - } finally { - JcrUtils.closeQuietly(binary); - IOUtils.closeQuietly(in); - // JcrUtils.discardQuietly(session); - } - } - - @Override - protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { - try { - Node userHome = UserJcrUtils.getUserHome(session); - Node keyring; - if (userHome.hasNode(ARGEO_KEYRING)) - keyring = userHome.getNode(ARGEO_KEYRING); - else if (notYetSavedKeyring.get() != null) - keyring = notYetSavedKeyring.get(); - else - throw new ArgeoJcrException("Keyring not setup"); - - pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY).getString(), - JcrUtils.getBinaryAsBytes(keyring.getProperty(ARGEO_SALT)), - (int) keyring.getProperty(ARGEO_ITERATION_COUNT).getLong(), - (int) keyring.getProperty(ARGEO_KEY_LENGTH).getLong(), - keyring.getProperty(ARGEO_SECRET_KEY_ENCRYPTION).getString()); - - if (notYetSavedKeyring.get() != null) - notYetSavedKeyring.remove(); - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot handle key spec callback", e); - } - } - - /** The parent node must already exist at this path. */ - @Override - protected synchronized void encrypt(String path, InputStream unencrypted) { - // should be called first for lazy initialization - SecretKey secretKey = getSecretKey(); - - Binary binary = null; - InputStream in = null; - try { - Cipher cipher = createCipher(); - Node node; - if (!session.nodeExists(path)) { - String parentPath = JcrUtils.parentPath(path); - if (!session.nodeExists(parentPath)) - throw new ArgeoJcrException("No parent node of " + path); - Node parentNode = session.getNode(parentPath); - node = parentNode.addNode(JcrUtils.nodeNameFromPath(path)); - } else { - node = session.getNode(path); - } - node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); - SecureRandom random = new SecureRandom(); - byte[] iv = new byte[16]; - random.nextBytes(iv); - cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); - JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); - - in = new CipherInputStream(unencrypted, cipher); - binary = session.getValueFactory().createBinary(in); - node.setProperty(Property.JCR_DATA, binary); - session.save(); - } catch (Exception e) { - throw new ArgeoJcrException("Cannot encrypt", e); - } finally { - IOUtils.closeQuietly(unencrypted); - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } - - @Override - protected synchronized InputStream decrypt(String path) { - Binary binary = null; - InputStream encrypted = null; - Reader reader = null; - try { - if (!session.nodeExists(path)) { - char[] password = ask(); - reader = new CharArrayReader(password); - return new ByteArrayInputStream(IOUtils.toByteArray(reader)); - } else { - // should be called first for lazy initialisation - SecretKey secretKey = getSecretKey(); - - Cipher cipher = createCipher(); - - Node node = session.getNode(path); - if (node.hasProperty(ARGEO_IV)) { - byte[] iv = JcrUtils.getBinaryAsBytes(node.getProperty(ARGEO_IV)); - cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); - } else { - cipher.init(Cipher.DECRYPT_MODE, secretKey); - } - - binary = node.getProperty(Property.JCR_DATA).getBinary(); - encrypted = binary.getStream(); - return new CipherInputStream(encrypted, cipher); - } - } catch (Exception e) { - throw new ArgeoJcrException("Cannot decrypt", e); - } finally { - IOUtils.closeQuietly(encrypted); - IOUtils.closeQuietly(reader); - JcrUtils.closeQuietly(binary); - } - } - - protected Cipher createCipher() { - try { - Node userHome = UserJcrUtils.getUserHome(session); - if (!userHome.hasNode(ARGEO_KEYRING)) - throw new ArgeoJcrException("Keyring not setup"); - Node keyring = userHome.getNode(ARGEO_KEYRING); - String cipherName = keyring.getProperty(ARGEO_CIPHER).getString(); - Provider securityProvider = getSecurityProvider(); - Cipher cipher; - if (securityProvider == null)// TODO use BC? - cipher = Cipher.getInstance(cipherName); - else - cipher = Cipher.getInstance(cipherName, securityProvider); - return cipher; - } catch (Exception e) { - throw new ArgeoJcrException("Cannot get cipher", e); - } - } - - public synchronized void changePassword(char[] oldPassword, char[] newPassword) { - // TODO decrypt with old pw / encrypt with new pw all argeo:encrypted - } - - public synchronized void setSession(Session session) { - this.session = session; - } - - public void setIterationCountFactor(Integer iterationCountFactor) { - this.iterationCountFactor = iterationCountFactor; - } - - public void setSecreteKeyLength(Long keyLength) { - this.secreteKeyLength = keyLength; - } - - public void setSecreteKeyFactoryName(String secreteKeyFactoryName) { - this.secreteKeyFactoryName = secreteKeyFactoryName; - } - - public void setSecreteKeyEncryption(String secreteKeyEncryption) { - this.secreteKeyEncryption = secreteKeyEncryption; - } - - public void setCipherName(String cipherName) { - this.cipherName = cipherName; - } - -} \ No newline at end of file diff --git a/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularRowIterator.java b/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularRowIterator.java deleted file mode 100644 index d4ffbf8c2..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularRowIterator.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.tabular; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.util.CsvParser; -import org.argeo.util.tabular.ArrayTabularRow; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularRow; -import org.argeo.util.tabular.TabularRowIterator; - -/** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */ -public class JcrTabularRowIterator implements TabularRowIterator { - private Boolean hasNext = null; - private Boolean parsingCompleted = false; - - private Long currentRowNumber = 0l; - - private List header = new ArrayList(); - - /** referenced so that we can close it */ - private Binary binary; - private InputStream in; - - private CsvParser csvParser; - private ArrayBlockingQueue> textLines; - - public JcrTabularRowIterator(Node tableNode) { - try { - for (NodeIterator it = tableNode.getNodes(); it.hasNext();) { - Node node = it.nextNode(); - if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) { - Integer type = PropertyType.valueFromName(node.getProperty( - Property.JCR_REQUIRED_TYPE).getString()); - TabularColumn tc = new TabularColumn(node.getProperty( - Property.JCR_TITLE).getString(), type); - header.add(tc); - } - } - Node contentNode = tableNode.getNode(Property.JCR_CONTENT); - if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) { - textLines = new ArrayBlockingQueue>(1000); - csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, - List header, List tokens) { - try { - textLines.put(tokens); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // textLines.add(tokens); - if (hasNext == null) { - hasNext = true; - synchronized (JcrTabularRowIterator.this) { - JcrTabularRowIterator.this.notifyAll(); - } - } - } - }; - csvParser.setNoHeader(true); - binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); - in = binary.getStream(); - Thread thread = new Thread(contentNode.getPath() + " reader") { - public void run() { - try { - csvParser.parse(in); - } finally { - parsingCompleted = true; - IOUtils.closeQuietly(in); - } - } - }; - thread.start(); - } - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot read table " + tableNode, e); - } - } - - public synchronized boolean hasNext() { - // we don't know if there is anything available - // while (hasNext == null) - // try { - // wait(); - // } catch (InterruptedException e) { - // // silent - // // FIXME better deal with interruption - // Thread.currentThread().interrupt(); - // break; - // } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // maybe the parsing is finished but the flag has not been set - while (!parsingCompleted && textLines.isEmpty()) - try { - wait(100); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - Thread.currentThread().interrupt(); - break; - } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // (parsingCompleted && textLines.isEmpty()) - return false; - - // if (!hasNext && textLines.isEmpty()) { - // if (in != null) { - // IOUtils.closeQuietly(in); - // in = null; - // } - // if (binary != null) { - // JcrUtils.closeQuietly(binary); - // binary = null; - // } - // return false; - // } else - // return true; - } - - public synchronized TabularRow next() { - try { - List tokens = textLines.take(); - List objs = new ArrayList(tokens.size()); - for (String token : tokens) { - // TODO convert to other formats using header - objs.add(token); - } - currentRowNumber++; - return new ArrayTabularRow(objs); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public Long getCurrentRowNumber() { - return currentRowNumber; - } - - public List getHeader() { - return header; - } - -} diff --git a/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularWriter.java b/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularWriter.java deleted file mode 100644 index c3fd97cbd..000000000 --- a/org.argeo.jcr/src/org/argeo/jcr/tabular/JcrTabularWriter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.tabular; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.List; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.jcr.ArgeoJcrException; -import org.argeo.jcr.ArgeoTypes; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.CsvWriter; -import org.argeo.util.tabular.TabularColumn; -import org.argeo.util.tabular.TabularWriter; - -/** Write / reference tabular content in a JCR repository. */ -public class JcrTabularWriter implements TabularWriter { - private Node contentNode; - private ByteArrayOutputStream out; - private CsvWriter csvWriter; - - @SuppressWarnings("unused") - private final List columns; - - /** Creates a table node */ - public JcrTabularWriter(Node tableNode, List columns, - String contentNodeType) { - try { - this.columns = columns; - for (TabularColumn column : columns) { - String normalized = JcrUtils.replaceInvalidChars(column - .getName()); - Node columnNode = tableNode.addNode(normalized, - ArgeoTypes.ARGEO_COLUMN); - columnNode.setProperty(Property.JCR_TITLE, column.getName()); - if (column.getType() != null) - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.nameFromValue(column.getType())); - else - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.TYPENAME_STRING); - } - contentNode = tableNode.addNode(Property.JCR_CONTENT, - contentNodeType); - if (contentNodeType.equals(ArgeoTypes.ARGEO_CSV)) { - contentNode.setProperty(Property.JCR_MIMETYPE, "text/csv"); - contentNode.setProperty(Property.JCR_ENCODING, "UTF-8"); - out = new ByteArrayOutputStream(); - csvWriter = new CsvWriter(out); - } - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot create table node " + tableNode, e); - } - } - - public void appendRow(Object[] row) { - csvWriter.writeLine(row); - } - - public void close() { - Binary binary = null; - InputStream in = null; - try { - // TODO parallelize with pipes and writing from another thread - in = new ByteArrayInputStream(out.toByteArray()); - binary = contentNode.getSession().getValueFactory() - .createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - } catch (RepositoryException e) { - throw new ArgeoJcrException("Cannot store data in " + contentNode, e); - } finally { - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } -} diff --git a/org.argeo.node.api/src/org/argeo/node/ArgeoNames.java b/org.argeo.node.api/src/org/argeo/node/ArgeoNames.java new file mode 100644 index 000000000..874057be8 --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/ArgeoNames.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.node; + +/** JCR names in the http://www.argeo.org/argeo namespace */ +public interface ArgeoNames { + public final static String ARGEO_NAMESPACE = "http://www.argeo.org/ns/argeo"; + public final static String ARGEO = "argeo"; + + public final static String ARGEO_URI = "argeo:uri"; + public final static String ARGEO_USER_ID = "argeo:userID"; + public final static String ARGEO_PREFERENCES = "argeo:preferences"; + public final static String ARGEO_DATA_MODEL_VERSION = "argeo:dataModelVersion"; + + public final static String ARGEO_REMOTE = "argeo:remote"; + public final static String ARGEO_PASSWORD = "argeo:password"; +// public final static String ARGEO_REMOTE_ROLES = "argeo:remoteRoles"; + + // user profile + public final static String ARGEO_PROFILE = "argeo:profile"; + + // spring security + public final static String ARGEO_ENABLED = "argeo:enabled"; + public final static String ARGEO_ACCOUNT_NON_EXPIRED = "argeo:accountNonExpired"; + public final static String ARGEO_ACCOUNT_NON_LOCKED = "argeo:accountNonLocked"; + public final static String ARGEO_CREDENTIALS_NON_EXPIRED = "argeo:credentialsNonExpired"; + + // personal details + public final static String ARGEO_FIRST_NAME = "argeo:firstName"; + public final static String ARGEO_LAST_NAME = "argeo:lastName"; + public final static String ARGEO_PRIMARY_EMAIL = "argeo:primaryEmail"; + public final static String ARGEO_PRIMARY_ORGANIZATION = "argeo:primaryOrganization"; + + // tabular + public final static String ARGEO_IS_KEY = "argeo:isKey"; + + // crypto + public final static String ARGEO_IV = "argeo:iv"; + public final static String ARGEO_SECRET_KEY_FACTORY = "argeo:secretKeyFactory"; + public final static String ARGEO_SALT = "argeo:salt"; + public final static String ARGEO_ITERATION_COUNT = "argeo:iterationCount"; + public final static String ARGEO_KEY_LENGTH = "argeo:keyLength"; + public final static String ARGEO_SECRET_KEY_ENCRYPTION = "argeo:secretKeyEncryption"; + public final static String ARGEO_CIPHER = "argeo:cipher"; + public final static String ARGEO_KEYRING = "argeo:keyring"; +} diff --git a/org.argeo.node.api/src/org/argeo/node/ArgeoTypes.java b/org.argeo.node.api/src/org/argeo/node/ArgeoTypes.java new file mode 100644 index 000000000..8158abe6b --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/ArgeoTypes.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.node; + +/** JCR types in the http://www.argeo.org/argeo namespace */ +public interface ArgeoTypes { + public final static String ARGEO_LINK = "argeo:link"; + public final static String ARGEO_USER_HOME = "argeo:userHome"; + public final static String ARGEO_USER_PROFILE = "argeo:userProfile"; + public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository"; + public final static String ARGEO_PREFERENCE_NODE = "argeo:preferenceNode"; + + // data model + public final static String ARGEO_DATA_MODEL = "argeo:dataModel"; + + // tabular + public final static String ARGEO_TABLE = "argeo:table"; + public final static String ARGEO_COLUMN = "argeo:column"; + public final static String ARGEO_CSV = "argeo:csv"; + + // crypto + public final static String ARGEO_ENCRYPTED = "argeo:encrypted"; + public final static String ARGEO_PBE_SPEC = "argeo:pbeSpec"; + +} diff --git a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java index 477b0b96b..dcff9a545 100644 --- a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java +++ b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java @@ -1,5 +1,7 @@ package org.argeo.node; +import javax.jcr.Repository; + public interface NodeConstants { /* * PIDs @@ -8,7 +10,7 @@ public interface NodeConstants { String NODE_DEPLOYMENT_PID = "org.argeo.node.deployment"; String NODE_INSTANCE_PID = "org.argeo.node.instance"; -// String NODE_REPO_PID = "org.argeo.node.repo"; + // String NODE_REPO_PID = "org.argeo.node.repo"; String NODE_USER_ADMIN_PID = "org.argeo.node.userAdmin"; /* @@ -42,9 +44,28 @@ public interface NodeConstants { String CN = "cn"; String OU = "ou"; String LABELED_URI = "labeledUri"; - + /* * STANDARD VALUES */ String DEFAULT = "default"; + /* + * LEGACY + */ + String ARGEO_BASE_PATH = "/argeo:system"; + String PEOPLE_BASE_PATH = NodeConstants.ARGEO_BASE_PATH + "/argeo:people"; + String DATA_MODELS_BASE_PATH = NodeConstants.ARGEO_BASE_PATH + + "/argeo:dataModels"; + String ALIAS_HOME = "home"; + // standard aliases + /** + * Reserved alias for the "node" {@link Repository}, that is, the default + * JCR repository. + */ + String ALIAS_NODE = "node"; + /** Key for a JCR repository URI */ + String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; + // parameters (typically for call to a RepositoryFactory) + /** Key for a JCR repository alias */ + String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias"; } diff --git a/org.argeo.node.api/src/org/argeo/node/NodeUtils.java b/org.argeo.node.api/src/org/argeo/node/NodeUtils.java new file mode 100644 index 000000000..e1fb21adb --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/NodeUtils.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.node; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryResult; +import javax.jcr.query.qom.Constraint; +import javax.jcr.query.qom.DynamicOperand; +import javax.jcr.query.qom.QueryObjectModelFactory; +import javax.jcr.query.qom.Selector; +import javax.jcr.query.qom.StaticOperand; + +/** Utilities related to Argeo model in JCR */ +public class NodeUtils { + /** + * Wraps the call to the repository factory based on parameter + * {@link NodeConstants#JCR_REPOSITORY_ALIAS} in order to simplify it and + * protect against future API changes. + */ + public static Repository getRepositoryByAlias( + RepositoryFactory repositoryFactory, String alias) { + try { + Map parameters = new HashMap(); + parameters.put(NodeConstants.JCR_REPOSITORY_ALIAS, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new RuntimeException( + "Unexpected exception when trying to retrieve repository with alias " + + alias, e); + } + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link NodeConstants#JCR_REPOSITORY_URI} in order to simplify it and + * protect against future API changes. + */ + public static Repository getRepositoryByUri( + RepositoryFactory repositoryFactory, String uri) { + return getRepositoryByUri(repositoryFactory, uri, null); + } + + /** + * Wraps the call to the repository factory based on parameter + * {@link NodeConstants#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 parameters = new HashMap(); + parameters.put(NodeConstants.JCR_REPOSITORY_URI, uri); + if (alias != null) + parameters.put(NodeConstants.JCR_REPOSITORY_ALIAS, alias); + return repositoryFactory.getRepository(parameters); + } catch (RepositoryException e) { + throw new RuntimeException( + "Unexpected exception when trying to retrieve repository with uri " + + uri, e); + } + } + + private NodeUtils() { + } + + /** + * Returns the home node of the user or null if none was found. + * + * @param session + * the session to use in order to perform the search, this can be + * a session with a different user ID than the one searched, + * typically when a system or admin session is used. + * @param username + * the username of the user + */ + public static Node getUserHome(Session session, String username) { + try { + // String homePath = UserJcrUtils.getUserHomePath(username); + // return session.itemExists(homePath) ? session.getNode(homePath) + // : null; + // kept for example of QOM queries + QueryObjectModelFactory qomf = session.getWorkspace() + .getQueryManager().getQOMFactory(); + Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME, + "userHome"); + DynamicOperand userIdDop = qomf.propertyValue( + userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); + StaticOperand userIdSop = qomf.literal(session.getValueFactory() + .createValue(username)); + Constraint constraint = qomf.comparison(userIdDop, + QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); + Query query = qomf.createQuery(userHomeSel, constraint, null, null); + return querySingleNode(query); + } catch (RepositoryException e) { + throw new RuntimeException("Cannot find home for user " + username, e); + } + } + + /** + * Queries one single node. + * + * @return one single node or null if none was found + * @throws ArgeoJcrException + * if more than one node was found + */ + private static Node querySingleNode(Query query) { + NodeIterator nodeIterator; + try { + QueryResult queryResult = query.execute(); + nodeIterator = queryResult.getNodes(); + } catch (RepositoryException e) { + throw new RuntimeException("Cannot execute query " + query, e); + } + Node node; + if (nodeIterator.hasNext()) + node = nodeIterator.nextNode(); + else + return null; + + if (nodeIterator.hasNext()) + throw new RuntimeException("Query returned more than one node."); + return node; + } + + /** Returns the home node of the session user or null if none was found. */ + public static Node getUserHome(Session session) { + String userID = session.getUserID(); + return getUserHome(session, userID); + } + + public static Node getUserProfile(Session session, String username) { + try { + QueryObjectModelFactory qomf = session.getWorkspace() + .getQueryManager().getQOMFactory(); + Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_PROFILE, + "userProfile"); + DynamicOperand userIdDop = qomf.propertyValue( + userHomeSel.getSelectorName(), ArgeoNames.ARGEO_USER_ID); + StaticOperand userIdSop = qomf.literal(session.getValueFactory() + .createValue(username)); + Constraint constraint = qomf.comparison(userIdDop, + QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop); + Query query = qomf.createQuery(userHomeSel, constraint, null, null); + return querySingleNode(query); + } catch (RepositoryException e) { + throw new RuntimeException( + "Cannot find profile for user " + username, e); + } + } + +}