<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Bundle-Name: JCR Explorer
Bundle-SymbolicName: org.argeo.jcr.ui.explorer;singleton:=true
Bundle-Version: 0.3.4.SNAPSHOT
-Bundle-Activator: org.argeo.eclipse.ui.jcr.explorer.JcrExplorerPlugin
+Bundle-Activator: org.argeo.jcr.ui.explorer.JcrExplorerPlugin
Bundle-Vendor: Argeo
Require-Bundle: org.eclipse.ui;resolution:=optional,
- org.eclipse.core.runtime,
- org.eclipse.rap.ui;resolution:=optional
+ org.eclipse.core.runtime;resolution:=optional,
+ org.eclipse.rap.ui;resolution:=optional,
+ org.eclipse.rap.ui.workbench;resolution:=optional
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
-Import-Package: javax.jcr;version="2.0.0",
+Import-Package: javax.jcr,
+ javax.jcr.nodetype,
+ javax.jcr.observation,
+ org.apache.commons.io,
+ org.apache.commons.logging,
+ org.argeo,
org.argeo.eclipse.spring,
+ org.argeo.eclipse.ui,
+ org.argeo.eclipse.ui.jcr,
org.argeo.eclipse.ui.jcr.commands,
org.argeo.eclipse.ui.jcr.editors,
+ org.argeo.eclipse.ui.jcr.utils,
org.argeo.eclipse.ui.jcr.views,
- org.argeo.jcr
-Export-Package: org.argeo.eclipse.ui.jcr.explorer
+ org.argeo.eclipse.ui.specific,
+ org.argeo.eclipse.ui.utils,
+ org.argeo.jcr,
+ org.argeo.jcr.spring,
+ org.argeo.util,
+ org.eclipse.ui.forms,
+ org.eclipse.ui.forms.editor,
+ org.eclipse.ui.forms.events,
+ org.eclipse.ui.forms.widgets,
+ org.springframework.context
+Export-Package: org.argeo.jcr.ui.explorer,
+ org.argeo.jcr.ui.explorer.browser;
+ uses:="javax.jcr,
+ org.argeo.eclipse.ui.jcr,
+ org.argeo.jcr,
+ org.argeo,
+ org.eclipse.jface.viewers,
+ org.eclipse.jface.resource,
+ org.eclipse.swt.graphics,
+ javax.jcr.nodetype,
+ org.argeo.eclipse.ui,
+ javax.jcr.observation",
+ org.argeo.jcr.ui.explorer.dialogs;
+ uses:="org.eclipse.swt.graphics,
+ org.eclipse.swt.widgets,
+ org.eclipse.swt.layout,
+ org.eclipse.jface.dialogs",
+ org.argeo.jcr.ui.explorer.wizards;
+ uses:="javax.jcr,
+ org.argeo,
+ org.eclipse.jface.operation,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.wizard,
+ org.apache.commons.logging,
+ org.argeo.eclipse.ui.dialogs,
+ org.argeo.eclipse.ui.specific,
+ org.apache.commons.io,
+ org.eclipse.swt.widgets,
+ org.eclipse.jface.dialogs"
+
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="openGenericJcrQueryEditor"
- class="org.argeo.eclipse.ui.jcr.commands.OpenGenericJcrQueryEditor"
+ class="org.argeo.jcr.ui.explorer.commands.OpenGenericJcrQueryEditor"
scope="prototype">
<property name="editorId"
value="org.argeo.slc.client.ui.dist.genericJcrQueryEditor" />
</bean>
+ <bean id="openGenericNodeEditor"
+ class="org.argeo.jcr.ui.explorer.commands.OpenGenericNodeEditor"
+ scope="prototype">
+ </bean>
+
<bean id="addFileFolder" class="org.argeo.eclipse.ui.jcr.commands.AddFileFolder"
scope="prototype" />
<bean id="deleteNode" class="org.argeo.eclipse.ui.jcr.commands.DeleteNode"
scope="prototype" />
- <bean id="importFileSystem" class="org.argeo.eclipse.ui.jcr.commands.ImportFileSystem"
+ <bean id="importFileSystem" class="org.argeo.jcr.ui.explorer.commands.ImportFileSystem"
scope="prototype" />
</beans>
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
- <bean id="genericJcrQueryEditor"
- class="org.argeo.eclipse.ui.jcr.editors.GenericJcrQueryEditor" scope="prototype">
+ <bean id="genericJcrQueryEditor" class="org.argeo.jcr.ui.explorer.editors.GenericJcrQueryEditor"
+ scope="prototype">
+ </bean>
+ <bean id="genericNodeEditor" class="org.argeo.jcr.ui.explorer.editors.GenericNodeEditor"
+ scope="prototype">
</bean>
</beans>
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Views -->
- <bean id="browserView" class="org.argeo.eclipse.ui.jcr.views.GenericJcrBrowser"
+ <bean id="browserView" class="org.argeo.jcr.ui.explorer.views.GenericJcrBrowser"
scope="prototype">
<property name="repositoryRegister" ref="repositoryRegister" />
</bean>
-source.. = src/main/java/
+source.. = src/main/java/,\
+ src/main/resources
output.. = target/classes/
bin.includes = META-INF/,\
.,\
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
+ <!-- Perspectives -->
<extension
point="org.eclipse.ui.perspectives">
<perspective
- class="org.argeo.eclipse.ui.jcr.explorer.JcrExplorerPerspective"
+ class="org.argeo.jcr.ui.explorer.JcrExplorerPerspective"
icon="icons/nodes.gif"
id="org.argeo.jcr.ui.explorer.perspective"
name="JCR Explorer">
</perspective>
</extension>
+ <!-- Views -->
<extension
point="org.eclipse.ui.views">
<view
name="JCR Browser">
</view>
</extension>
+ <!-- Editors -->
<extension
point="org.eclipse.ui.editors">
<editor
name="JCR Query"
icon="icons/query.png"
default="false">
+ </editor>
+ <editor
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ id="org.argeo.jcr.ui.explorer.genericNodeEditor"
+ name="Node Editor"
+ icon="icons/query.png"
+ default="false">
</editor>
</extension>
+ <!-- Commands -->
<extension
point="org.eclipse.ui.commands">
<command
id="org.argeo.jcr.ui.explorer.openGenericJcrQueryEditor"
name="New generic JCR query">
</command>
+ <command
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ id="org.argeo.jcr.ui.explorer.openGenericNodeEditor"
+ name="Open generic node Editor">
+ <commandParameter
+ id="org.argeo.jcr.ui.explorer.nodePath"
+ name="Node path">
+ </commandParameter>
+ </command>
<command
defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
id="org.argeo.jcr.ui.explorer.addFileFolder"
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.commons.server</groupId>
<version>0.3.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.argeo.commons.eclipse</groupId>
+ <artifactId>org.argeo.eclipse.ui.rcp</artifactId>
+ <version>0.3.4-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+package org.argeo.jcr.ui.explorer;
+
+/** Constants used across the application. */
+public interface JcrExplorerConstants {
+
+ /*
+ * MISCEALLENEOUS
+ */
+ public final static String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm";
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class JcrExplorerPerspective implements IPerspectiveFactory {
+ public static String BROWSER_VIEW_ID = JcrExplorerPlugin.ID
+ + ".browserView";
+
+ public void createInitialLayout(IPageLayout layout) {
+ layout.setEditorAreaVisible(true);
+
+ IFolderLayout upperLeft = layout.createFolder(JcrExplorerPlugin.ID
+ + ".upperLeft", IPageLayout.LEFT, 0.4f, layout.getEditorArea());
+ upperLeft.addView(BROWSER_VIEW_ID);
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer;
+
+import java.util.ResourceBundle;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class JcrExplorerPlugin extends AbstractUIPlugin {
+ private final static Log log = LogFactory.getLog(JcrExplorerPlugin.class);
+ private ResourceBundle messages;
+
+ // The plug-in ID
+ public static final String ID = "org.argeo.jcr.ui.explorer"; //$NON-NLS-1$
+
+ // The shared instance
+ private static JcrExplorerPlugin plugin;
+
+ /**
+ * The constructor
+ */
+ public JcrExplorerPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+ * )
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ messages = ResourceBundle
+ .getBundle("org.argeo.jcr.ui.explorer.messages");
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+ * )
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static JcrExplorerPlugin getDefault() {
+ return plugin;
+ }
+
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(ID, path);
+ }
+
+ /** Returns the internationalized label for the given key */
+ public static String getMessage(String key) {
+ try {
+ return getDefault().messages.getString(key);
+ } catch (NullPointerException npe) {
+ log.warn(key + " not found.");
+ return key;
+ }
+ }
+
+ /**
+ * Gives access to the internationalization message bundle. Returns null in
+ * case the ClientUiPlugin is not started (for JUnit tests, by instance)
+ */
+ public static ResourceBundle getMessagesBundle() {
+ if (getDefault() != null)
+ // To avoid NPE
+ return getDefault().messages;
+ else
+ return null;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer;
+
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+
+public class JcrExplorerView extends GenericJcrBrowser {
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import javax.jcr.Session;
+
+import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider;
+import org.argeo.jcr.JcrUtils;
+
+public class HomeContentProvider extends SimpleNodeContentProvider {
+
+ public HomeContentProvider(Session session) {
+ super(session, new String[] { JcrUtils.getUserHomePath(session) });
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import java.util.Comparator;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+
+public class ItemComparator implements Comparator<Item> {
+ public int compare(Item o1, Item o2) {
+ try {
+ // TODO: put folder before files
+ return o1.getName().compareTo(o2.getName());
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot compare " + o1 + " and " + o2, e);
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.RepositoryRegister;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class NodeContentProvider implements ITreeContentProvider {
+ private ItemComparator itemComparator = new ItemComparator();
+
+ private RepositoryRegister repositoryRegister;
+ private Session userSession;
+
+ public NodeContentProvider(Session userSession,
+ RepositoryRegister repositoryRegister) {
+ this.userSession = userSession;
+ this.repositoryRegister = repositoryRegister;
+ }
+
+ /**
+ * Sends back the first level of the Tree. Independent from inputElement
+ * that can be null
+ */
+ public Object[] getElements(Object inputElement) {
+ List<Object> objs = new ArrayList<Object>();
+ if (userSession != null) {
+ Node userHome = JcrUtils.getUserHome(userSession);
+ if (userHome != null)
+ objs.add(userHome);
+ }
+ if (repositoryRegister != null)
+ objs.add(repositoryRegister);
+ return objs.toArray();
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof Node) {
+ return childrenNodes((Node) parentElement);
+ } else if (parentElement instanceof RepositoryNode) {
+ return ((RepositoryNode) parentElement).getChildren();
+ } else if (parentElement instanceof WorkspaceNode) {
+ Session session = ((WorkspaceNode) parentElement).getSession();
+ if (session == null)
+ return new Object[0];
+
+ try {
+ return childrenNodes(session.getRootNode());
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot retrieve root node of "
+ + session, e);
+ }
+ } else if (parentElement instanceof RepositoryRegister) {
+ RepositoryRegister repositoryRegister = (RepositoryRegister) parentElement;
+ List<RepositoryNode> nodes = new ArrayList<RepositoryNode>();
+ Map<String, Repository> repositories = repositoryRegister
+ .getRepositories();
+ for (String name : repositories.keySet()) {
+ nodes.add(new RepositoryNode(name, repositories.get(name)));
+ }
+ return nodes.toArray();
+ } else {
+ return new Object[0];
+ }
+ }
+
+ public Object getParent(Object element) {
+ try {
+ if (element instanceof Node) {
+ Node node = (Node) element;
+ if (!node.getPath().equals("/"))
+ return node.getParent();
+ else
+ return null;
+ }
+ return null;
+ } catch (RepositoryException e) {
+ return null;
+ }
+ }
+
+ public boolean hasChildren(Object element) {
+ try {
+ if (element instanceof Node) {
+ return ((Node) element).hasNodes();
+ } else if (element instanceof RepositoryNode) {
+ return ((RepositoryNode) element).hasChildren();
+ } else if (element instanceof WorkspaceNode) {
+ return ((WorkspaceNode) element).getSession() != null;
+ } else if (element instanceof RepositoryRegister) {
+ return ((RepositoryRegister) element).getRepositories().size() > 0;
+ }
+ return false;
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot check children of " + element, e);
+ }
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ protected Object[] childrenNodes(Node parentNode) {
+ try {
+ List<Node> children = new ArrayList<Node>();
+ NodeIterator nit = parentNode.getNodes();
+ while (nit.hasNext()) {
+ Node node = nit.nextNode();
+ children.add(node);
+ }
+ Node[] arr = children.toArray(new Node[children.size()]);
+ Arrays.sort(arr, itemComparator);
+ return arr;
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot list children of " + parentNode, e);
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider;
+import org.argeo.eclipse.ui.jcr.JcrUiPlugin;
+import org.argeo.jcr.RepositoryRegister;
+import org.eclipse.swt.graphics.Image;
+
+public class NodeLabelProvider extends DefaultNodeLabelProvider {
+ // Images
+ public final static Image REPOSITORIES = JcrUiPlugin.getImageDescriptor(
+ "icons/repositories.gif").createImage();
+
+ public String getText(Object element) {
+ if (element instanceof RepositoryRegister) {
+ return "Repositories";
+ }
+ return super.getText(element);
+ }
+
+ protected String getText(Node node) throws RepositoryException {
+ String label = node.getName();
+ StringBuffer mixins = new StringBuffer("");
+ for (NodeType type : node.getMixinNodeTypes())
+ mixins.append(' ').append(type.getName());
+
+ return label + " [" + node.getPrimaryNodeType().getName() + mixins
+ + "]";
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof RepositoryNode) {
+ if (((RepositoryNode) element).getDefaultSession() == null)
+ return RepositoryNode.REPOSITORY_DISCONNECTED;
+ else
+ return RepositoryNode.REPOSITORY_CONNECTED;
+ } else if (element instanceof WorkspaceNode) {
+ if (((WorkspaceNode) element).getSession() == null)
+ return WorkspaceNode.WORKSPACE_DISCONNECTED;
+ else
+ return WorkspaceNode.WORKSPACE_CONNECTED;
+ } else if (element instanceof RepositoryRegister) {
+ return REPOSITORIES;
+ }
+ return super.getImage(element);
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class PropertiesContentProvider implements IStructuredContentProvider {
+ private ItemComparator itemComparator = new ItemComparator();
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public Object[] getElements(Object inputElement) {
+ try {
+ if (inputElement instanceof Node) {
+ Set<Property> props = new TreeSet<Property>(itemComparator);
+ PropertyIterator pit = ((Node) inputElement).getProperties();
+ while (pit.hasNext())
+ props.add(pit.nextProperty());
+ return props.toArray();
+ }
+ return new Object[] {};
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot get element for " + inputElement,
+ e);
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.jcr.JcrUiPlugin;
+import org.eclipse.swt.graphics.Image;
+
+public class RepositoryNode extends TreeParent {
+ private final String name;
+ private final Repository repository;
+ private Session defaultSession = null;
+ public final static Image REPOSITORY_DISCONNECTED = JcrUiPlugin
+ .getImageDescriptor("icons/repository_disconnected.gif")
+ .createImage();
+ public final static Image REPOSITORY_CONNECTED = JcrUiPlugin
+ .getImageDescriptor("icons/repository_connected.gif").createImage();
+
+ public RepositoryNode(String name, Repository repository) {
+ super(name);
+ this.name = name;
+ this.repository = repository;
+ }
+
+ public void login() {
+ try {
+ defaultSession = repository.login();
+ String[] wkpNames = defaultSession.getWorkspace()
+ .getAccessibleWorkspaceNames();
+ for (String wkpName : wkpNames) {
+ if (wkpName.equals(defaultSession.getWorkspace().getName()))
+ addChild(new WorkspaceNode(repository, wkpName,
+ defaultSession));
+ else
+ addChild(new WorkspaceNode(repository, wkpName));
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot connect to repository " + name, e);
+ }
+ }
+
+ public Session getDefaultSession() {
+ return defaultSession;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.browser;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.jcr.JcrUiPlugin;
+import org.eclipse.swt.graphics.Image;
+
+public class WorkspaceNode extends TreeParent implements EventListener {
+ private final String name;
+ private final Repository repository;
+ private Session session = null;
+ public final static Image WORKSPACE_DISCONNECTED = JcrUiPlugin
+ .getImageDescriptor("icons/workspace_disconnected.png")
+ .createImage();
+ public final static Image WORKSPACE_CONNECTED = JcrUiPlugin
+ .getImageDescriptor("icons/workspace_connected.png").createImage();
+
+ public WorkspaceNode(Repository repository, String name) {
+ this(repository, name, null);
+ }
+
+ public WorkspaceNode(Repository repository, String name, Session session) {
+ super(name);
+ this.name = name;
+ this.repository = repository;
+ this.session = session;
+ if (session != null)
+ processNewSession(session);
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ public void login() {
+ try {
+ logout();
+ session = repository.login(name);
+ processNewSession(session);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot connect to repository " + name, e);
+ }
+ }
+
+ public void logout() {
+ try {
+ if (session != null && session.isLive()) {
+ session.getWorkspace().getObservationManager()
+ .removeEventListener(this);
+ session.logout();
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot connect to repository " + name, e);
+ }
+ }
+
+ public void onEvent(final EventIterator events) {
+ // if (session == null)
+ // return;
+ // Display.getDefault().syncExec(new Runnable() {
+ // public void run() {
+ // while (events.hasNext()) {
+ // Event event = events.nextEvent();
+ // try {
+ // String path = event.getPath();
+ // String parentPath = path.substring(0,
+ // path.lastIndexOf('/'));
+ // final Object parent;
+ // if (parentPath.equals("/") || parentPath.equals(""))
+ // parent = this;
+ // else if (session.itemExists(parentPath)){
+ // parent = session.getItem(parentPath);
+ // ((Item)parent).refresh(false);
+ // }
+ // else
+ // parent = null;
+ // if (parent != null) {
+ // nodesViewer.refresh(parent);
+ // }
+ //
+ // } catch (RepositoryException e) {
+ // log.warn("Error processing event " + event, e);
+ // }
+ // }
+ // }
+ // });
+ }
+
+ protected void processNewSession(Session session) {
+ // try {
+ // ObservationManager observationManager = session.getWorkspace()
+ // .getObservationManager();
+ // observationManager.addEventListener(this, Event.NODE_ADDED
+ // | Event.NODE_REMOVED, "/", true, null, null, false);
+ // } catch (RepositoryException e) {
+ // throw new ArgeoException("Cannot process new session "
+ // + session, e);
+ // }
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.eclipse.ui.dialogs.Error;
+import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Generic command to open a path in an editor. */
+public class EditNode extends AbstractHandler {
+ public final static String EDITOR_PARAM = "editor";
+
+ private String defaultEditorId;
+
+ private Map<String, String> nodeTypeToEditor = new HashMap<String, String>();
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String path = event.getParameter(Property.JCR_PATH);
+
+ String type = event.getParameter(NodeType.NT_NODE_TYPE);
+ if (type == null)
+ type = NodeType.NT_UNSTRUCTURED;
+
+ String editorId = event.getParameter(NodeType.NT_NODE_TYPE);
+ if (editorId == null)
+ editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor
+ .get(type) : defaultEditorId;
+
+ NodeEditorInput nei = new NodeEditorInput(path);
+
+ try {
+ HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+ .openEditor(nei, editorId);
+ } catch (PartInitException e) {
+ Error.show("Cannot open " + editorId + " with " + path
+ + " of type " + type, e);
+ }
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setDefaultEditorId(String defaultEditorId) {
+ this.defaultEditorId = defaultEditorId;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.commands;
+
+import javax.jcr.Node;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.dialogs.Error;
+import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
+import org.argeo.jcr.ui.explorer.wizards.ImportFileSystemWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class ImportFileSystem extends AbstractHandler {
+ private static Log log = LogFactory.getLog(ImportFileSystem.class);
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+ AbstractJcrBrowser view = (AbstractJcrBrowser) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ try {
+ if (obj instanceof Node) {
+ Node folder = (Node) obj;
+ // if (!folder.getPrimaryNodeType().getName()
+ // .equals(NodeType.NT_FOLDER)) {
+ // Error.show("Can only import to a folder node");
+ // return null;
+ // }
+ ImportFileSystemWizard wizard = new ImportFileSystemWizard(
+ folder);
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), wizard);
+ dialog.open();
+ view.refresh(folder);
+ } else {
+ Error.show("Can only import to a node");
+ }
+ } catch (Exception e) {
+ Error.show("Cannot import files to " + obj, e);
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.commands;
+
+import org.argeo.eclipse.ui.jcr.editors.JcrQueryEditorInput;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Open a JCR query editor. */
+public class OpenGenericJcrQueryEditor extends AbstractHandler {
+ private String editorId;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ try {
+ JcrQueryEditorInput editorInput = new JcrQueryEditorInput("", null);
+ IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow(
+ event).getActivePage();
+ activePage.openEditor(editorInput, editorId);
+ } catch (Exception e) {
+ throw new ExecutionException("Cannot open editor", e);
+ }
+ return null;
+ }
+
+ public void setEditorId(String editorId) {
+ this.editorId = editorId;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.commands;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class OpenGenericNodeEditor extends AbstractHandler {
+ private final static Log log = LogFactory
+ .getLog(OpenGenericNodeEditor.class);
+ public final static String ID = "org.argeo.jcr.ui.explorer.openGenericNodeEditor";
+ public final static String PARAM_PATH = "org.argeo.jcr.ui.explorer.nodePath";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String path = event.getParameter(PARAM_PATH);
+ try {
+ NodeEditorInput nei = new NodeEditorInput(path);
+ HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+ .openEditor(nei, GenericNodeEditor.ID);
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot open editor", e);
+ }
+ return null;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.dialogs;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** Dialog to change the current user password */
+public class ChooseNameDialog extends TitleAreaDialog {
+ private Text nameT;
+
+ public ChooseNameDialog(Shell parentShell) {
+ super(parentShell);
+ setTitle("Choose name");
+ }
+
+ protected Point getInitialSize() {
+ return new Point(300, 250);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogarea = (Composite) super.createDialogArea(parent);
+ dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ Composite composite = new Composite(dialogarea, SWT.NONE);
+ composite.setLayout(new GridLayout(2, false));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ nameT = createLT(composite, "Name");
+
+ setMessage("Choose name", IMessageProvider.INFORMATION);
+ parent.pack();
+ return composite;
+ }
+
+ /** Creates label and text. */
+ protected Text createLT(Composite parent, String label) {
+ new Label(parent, SWT.NONE).setText(label);
+ Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ return text;
+ }
+
+ public String getName() {
+ return nameT.getText();
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * This page is only used at editor's creation time when current node has not
+ * yet been set
+ */
+public class EmptyNodePage extends FormPage {
+ private final static Log log = LogFactory.getLog(EmptyNodePage.class);
+
+ public EmptyNodePage(FormEditor editor, String title) {
+ super(editor, "Empty Page", title);
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ try {
+ ScrolledForm form = managedForm.getForm();
+ GridLayout twt = new GridLayout(1, false);
+ twt.marginWidth = twt.marginHeight = 0;
+ form.getBody().setLayout(twt);
+ Label lbl = new Label(form.getBody(), SWT.NONE);
+ lbl.setText("Empty page");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+
+/** Executes any JCR query. */
+public class GenericJcrQueryEditor extends AbstractJcrQueryEditor {
+ public final static String ID = "org.argeo.jcr.ui.explorer.genericJcrQueryEditor";
+
+ private Text queryField;
+
+ @Override
+ public void createQueryForm(Composite parent) {
+ parent.setLayout(new GridLayout(1, false));
+
+ queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP);
+ queryField.setText(initialQuery);
+ queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Button execute = new Button(parent, SWT.PUSH);
+ execute.setText("Execute");
+
+ Listener executeListener = new Listener() {
+ public void handleEvent(Event event) {
+ executeQuery(queryField.getText());
+ }
+ };
+
+ execute.addListener(SWT.Selection, executeListener);
+ // queryField.addListener(SWT.DefaultSelection, executeListener);
+ }
+
+ @Override
+ public void setFocus() {
+ queryField.setFocus();
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import javax.jcr.Node;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.FormEditor;
+
+/**
+ * Parent Abstract GR multitab editor. Insure the presence of a GrBackend
+ */
+public class GenericNodeEditor extends FormEditor {
+
+ private final static Log log = LogFactory.getLog(GenericNodeEditor.class);
+ public final static String ID = "org.argeo.jcr.ui.explorer.genericNodeEditor";
+
+ private Node currentNode;
+
+ private GenericNodePage networkDetailsPage;
+
+ public void init(IEditorSite site, IEditorInput input)
+ throws PartInitException {
+ super.init(site, input);
+ GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput();
+ this.setPartName(JcrUtils.lastPathElement(nei.getPath()));
+ }
+
+ @Override
+ protected void addPages() {
+ EmptyNodePage enp = new EmptyNodePage(this, "Empty node page");
+ try {
+ addPage(enp);
+ } catch (PartInitException e) {
+ throw new ArgeoException("Not able to add an empty page ", e);
+ }
+ }
+
+ private void addPagesAfterNodeSet() {
+ try {
+ networkDetailsPage = new GenericNodePage(this,
+ JcrExplorerPlugin.getMessage("genericNodePageTitle"),
+ currentNode);
+ addPage(networkDetailsPage);
+ this.setActivePage(networkDetailsPage.getIndex());
+ } catch (PartInitException e) {
+ throw new ArgeoException("Not able to add page ", e);
+ }
+ }
+
+ @Override
+ public void doSaveAs() {
+ // unused compulsory method
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor) {
+ try {
+ // Automatically commit all pages of the editor
+ commitPages(true);
+ firePropertyChange(PROP_DIRTY);
+ } catch (Exception e) {
+ throw new ArgeoException("Error while saving node", e);
+ }
+
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ Node getCurrentNode() {
+ return currentNode;
+ }
+
+ public void setCurrentNode(Node currentNode) {
+ boolean nodeWasNull = this.currentNode == null;
+ this.currentNode = currentNode;
+ if (nodeWasNull) {
+ this.removePage(0);
+ addPagesAfterNodeSet();
+ }
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * An editor input based on a path to a node plus workspace name and repository
+ * alias. In a multirepository environment, path can be enriched with Repository
+ * Alias and workspace
+ */
+
+public class GenericNodeEditorInput implements IEditorInput {
+ private final String path;
+ private final String repositoryAlias;
+ private final String workspaceName;
+
+ /**
+ * In order to implement a generic explorer that supports remote and multi
+ * workspaces repositories, node path can be detailed by these strings.
+ *
+ * @param repositoryAlias
+ * : can be null
+ * @param workspaceName
+ * : can be null
+ * @param path
+ */
+ public GenericNodeEditorInput(String repositoryAlias, String workspaceName,
+ String path) {
+ this.path = path;
+ this.repositoryAlias = repositoryAlias;
+ this.workspaceName = workspaceName;
+ }
+
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return path;
+ }
+
+ public String getRepositoryAlias() {
+ return repositoryAlias;
+ }
+
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+
+ GenericNodeEditorInput other = (GenericNodeEditorInput) obj;
+
+ if (!path.equals(other.getPath()))
+ return false;
+
+ String own = other.getWorkspaceName();
+ if ((workspaceName == null && own != null)
+ || (workspaceName != null && (own == null || !workspaceName
+ .equals(own))))
+ return false;
+
+ String ora = other.getRepositoryAlias();
+ if ((repositoryAlias == null && ora != null)
+ || (repositoryAlias != null && (ora == null || !repositoryAlias
+ .equals(ora))))
+ return false;
+
+ return true;
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+public class GenericNodePage extends FormPage implements JcrExplorerConstants {
+ private final static Log log = LogFactory.getLog(GenericNodePage.class);
+
+ // local constants
+ private final static String JCR_PROPERTY_NAME = "jcr:name";
+
+ // Utils
+ protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
+
+ // Main business Objects
+ private Node currentNode;
+
+ // This page widgets
+ private FormToolkit tk;
+ private List<Control> modifyableProperties = new ArrayList<Control>();
+
+ public GenericNodePage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "id", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ try {
+ tk = managedForm.getToolkit();
+ ScrolledForm form = managedForm.getForm();
+ GridLayout twt = new GridLayout(3, false);
+ twt.marginWidth = twt.marginHeight = 0;
+
+ form.getBody().setLayout(twt);
+
+ createPropertiesPart(form.getBody());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void createPropertiesPart(Composite parent) {
+ try {
+
+ PropertyIterator pi = currentNode.getProperties();
+
+ // Initializes form part
+ AbstractFormPart part = new AbstractFormPart() {
+ public void commit(boolean onSave) {
+ try {
+ if (onSave) {
+ ListIterator<Control> it = modifyableProperties
+ .listIterator();
+ while (it.hasNext()) {
+ // we only support Text controls for the time
+ // being
+ Text curControl = (Text) it.next();
+ String value = curControl.getText();
+ currentNode.setProperty((String) curControl
+ .getData(JCR_PROPERTY_NAME), value);
+ }
+
+ // We only commit when onSave = true,
+ // thus it is still possible to save after a tab
+ // change.
+ super.commit(onSave);
+ }
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Unexpected error while saving properties", re);
+ }
+ }
+ };
+
+ while (pi.hasNext()) {
+ Property prop = pi.nextProperty();
+ addPropertyLine(parent, part, prop);
+ }
+
+ getManagedForm().addPart(part);
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Error during creation of network details section", re);
+ }
+
+ }
+
+ private void addPropertyLine(Composite parent, AbstractFormPart part,
+ Property prop) {
+ try {
+ Label lbl = tk.createLabel(parent, prop.getName());
+ lbl = tk.createLabel(parent,
+ "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
+
+ if (prop.getDefinition().isProtected()) {
+ lbl = tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+ } else
+ addModifyableValueWidget(parent, part, prop);
+ } catch (RepositoryException re) {
+ throw new ArgeoException("Cannot get property " + prop, re);
+ }
+ }
+
+ private String formatReadOnlyPropertyValue(Property prop) {
+ try {
+ String strValue;
+
+ if (prop.getType() == PropertyType.BINARY)
+ strValue = "<binary>";
+ else if (prop.isMultiple())
+ strValue = Arrays.asList(prop.getValues()).toString();
+ else if (prop.getType() == PropertyType.DATE)
+ strValue = timeFormatter.format(prop.getValue().getDate()
+ .getTime());
+ else
+ strValue = prop.getValue().getString();
+
+ return strValue;
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Unexpected error while formatting read only property value",
+ re);
+ }
+ }
+
+ private Control addModifyableValueWidget(Composite parent,
+ AbstractFormPart part, Property prop) {
+ GridData gd;
+ try {
+ if (prop.getType() == PropertyType.STRING) {
+ Text txt = tk.createText(parent, prop.getString());
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ txt.setLayoutData(gd);
+ txt.addModifyListener(new ModifiedFieldListener(part));
+ txt.setData(JCR_PROPERTY_NAME, prop.getName());
+ modifyableProperties.add(txt);
+ } else {
+ // unsupported property type for editing, we create a read only
+ // label.
+ return tk
+ .createLabel(parent, formatReadOnlyPropertyValue(prop));
+ }
+ return null;
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Unexpected error while formatting read only property value",
+ re);
+ }
+
+ }
+
+ //
+ // LISTENERS
+ //
+
+ private class ModifiedFieldListener implements ModifyListener {
+
+ private AbstractFormPart formPart;
+
+ public ModifiedFieldListener(AbstractFormPart generalPart) {
+ this.formPart = generalPart;
+ }
+
+ public void modifyText(ModifyEvent e) {
+ formPart.markDirty();
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.utils;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.specific.FileHandler;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.browser.NodeContentProvider;
+import org.argeo.jcr.ui.explorer.browser.RepositoryNode;
+import org.argeo.jcr.ui.explorer.browser.WorkspaceNode;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditorInput;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.PartInitException;
+
+/**
+ *
+ * Centralizes the management of double click on a NodeTreeViewer
+ *
+ */
+public class GenericNodeDoubleClickListener implements IDoubleClickListener {
+
+ private final static Log log = LogFactory
+ .getLog(GenericNodeDoubleClickListener.class);
+
+ private TreeViewer nodeViewer;
+ private JcrFileProvider jfp;
+ private FileHandler fileHandler;
+
+ public GenericNodeDoubleClickListener(TreeViewer nodeViewer) {
+ this.nodeViewer = nodeViewer;
+ jfp = new JcrFileProvider();
+ fileHandler = new FileHandler(jfp);
+ }
+
+ public void doubleClick(DoubleClickEvent event) {
+ if (event.getSelection() == null || event.getSelection().isEmpty())
+ return;
+ Object obj = ((IStructuredSelection) event.getSelection())
+ .getFirstElement();
+ if (obj instanceof RepositoryNode) {
+ RepositoryNode rpNode = (RepositoryNode) obj;
+ rpNode.login();
+ nodeViewer.refresh(obj);
+ } else if (obj instanceof WorkspaceNode) {
+ ((WorkspaceNode) obj).login();
+ nodeViewer.refresh(obj);
+ } else if (obj instanceof Node) {
+ Node node = (Node) obj;
+ try {
+ if (node.isNodeType(NodeType.NT_FILE)) {
+ // double click on a file node triggers its opening
+ String name = node.getName();
+ String id = node.getIdentifier();
+
+ // For the file provider to be able to browse the
+ // various
+ // repository.
+ // TODO : enhanced that.
+ ITreeContentProvider itcp = (ITreeContentProvider) nodeViewer
+ .getContentProvider();
+ jfp.setRootNodes((Object[]) itcp.getElements(null));
+ fileHandler.openFile(name, id);
+ }
+ // File or not, we always open the corresponding node Editor.
+ String repositoryAlias = getRepositoryAlias(obj);
+ String workspaceName = node.getSession().getWorkspace()
+ .getName();
+ String path = node.getPath();
+
+ if (log.isDebugEnabled()) {
+ log.debug("RepoAlias: " + repositoryAlias + " - WS Name: "
+ + workspaceName + " - path:" + path);
+ }
+ GenericNodeEditorInput gnei = new GenericNodeEditorInput(
+ repositoryAlias, workspaceName, path);
+
+ GenericNodeEditor gne = (GenericNodeEditor) JcrExplorerPlugin
+ .getDefault().getWorkbench().getActiveWorkbenchWindow()
+ .getActivePage().openEditor(gnei, GenericNodeEditor.ID);
+ gne.setCurrentNode(node);
+
+ } catch (RepositoryException re) {
+ throw new ArgeoException(
+ "Repository error while getting node info", re);
+ } catch (PartInitException pie) {
+ throw new ArgeoException(
+ "Unexepected exception while opening node editor", pie);
+ }
+ }
+ }
+
+ // Enhance this method
+ private String getRepositoryAlias(Object element) {
+ NodeContentProvider ncp = (NodeContentProvider) nodeViewer
+ .getContentProvider();
+ Object parent = element;
+ while (!(ncp.getParent(parent) instanceof RepositoryNode)
+ && parent != null)
+ parent = ncp.getParent(parent);
+ return parent == null ? null : ((RepositoryNode) parent).getName();
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.utils;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.specific.FileProvider;
+import org.argeo.jcr.RepositoryRegister;
+import org.argeo.jcr.ui.explorer.browser.RepositoryNode;
+
+/**
+ * Implements a FileProvider for UI purposes. Note that it might not be very
+ * reliable as long as we have not fixed login & multi repository issues that
+ * will be addressed in the next version.
+ *
+ * NOTE: id used here is the real id of the JCR Node, not the JCR Path
+ *
+ * Relies on common approach for JCR file handling implementation.
+ *
+ */
+
+public class JcrFileProvider implements FileProvider {
+
+ private Object[] rootNodes;
+
+ /**
+ * Must be set in order for the provider to be able to search the repository
+ * Provided object might be either JCR Nodes or UI RepositoryNode for the
+ * time being.
+ *
+ * @param repositoryNode
+ */
+ public void setRootNodes(Object[] rootNodes) {
+ List<Object> tmpNodes = new ArrayList<Object>();
+ for (int i = 0; i < rootNodes.length; i++) {
+ Object obj = rootNodes[i];
+ if (obj instanceof Node) {
+ tmpNodes.add(obj);
+ } else if (obj instanceof RepositoryRegister) {
+ RepositoryRegister repositoryRegister = (RepositoryRegister) obj;
+ Map<String, Repository> repositories = repositoryRegister
+ .getRepositories();
+ for (String name : repositories.keySet()) {
+ tmpNodes.add(new RepositoryNode(name, repositories
+ .get(name)));
+ }
+
+ }
+ }
+ this.rootNodes = tmpNodes.toArray();
+ }
+
+ public byte[] getByteArrayFileFromId(String fileId) {
+ InputStream fis = null;
+ byte[] ba = null;
+ Node child = getFileNodeFromId(fileId);
+ try {
+ fis = (InputStream) child.getProperty(Property.JCR_DATA)
+ .getBinary().getStream();
+ ba = IOUtils.toByteArray(fis);
+
+ } catch (Exception e) {
+ throw new ArgeoException("Stream error while opening file", e);
+ } finally {
+ IOUtils.closeQuietly(fis);
+ }
+ return ba;
+ }
+
+ public InputStream getInputStreamFromFileId(String fileId) {
+ try {
+ InputStream fis = null;
+
+ Node child = getFileNodeFromId(fileId);
+ fis = (InputStream) child.getProperty(Property.JCR_DATA)
+ .getBinary().getStream();
+ return fis;
+ } catch (RepositoryException re) {
+ throw new ArgeoException("Cannot get stream from file node for Id "
+ + fileId, re);
+ }
+ }
+
+ /**
+ * Throws an exception if the node is not found in the current repository (a
+ * bit like a FileNotFoundException)
+ *
+ * @param fileId
+ * @return Returns the child node of the nt:file node. It is the child node
+ * that have the jcr:data property where actual file is stored.
+ * never null
+ */
+ private Node getFileNodeFromId(String fileId) {
+ try {
+ Node result = null;
+
+ rootNodes: for (int j = 0; j < rootNodes.length; j++) {
+ // in case we have a classic JCR Node
+ if (rootNodes[j] instanceof Node) {
+ Node curNode = (Node) rootNodes[j];
+ result = curNode.getSession().getNodeByIdentifier(fileId);
+ if (result != null)
+ break rootNodes;
+ } // Case of a repository Node
+ else if (rootNodes[j] instanceof RepositoryNode) {
+ Object[] nodes = ((RepositoryNode) rootNodes[j])
+ .getChildren();
+ for (int i = 0; i < nodes.length; i++) {
+ Node node = (Node) nodes[i];
+ result = node.getSession().getNodeByIdentifier(fileId);
+ if (result != null)
+ break rootNodes;
+ }
+ }
+ }
+
+ // Sanity checks
+ if (result == null)
+ throw new ArgeoException("File node not found for ID" + fileId);
+
+ // Ensure that the node have the correct type.
+ if (!result.isNodeType(NodeType.NT_FILE))
+ throw new ArgeoException(
+ "Cannot open file children Node that are not of '"
+ + NodeType.NT_RESOURCE + "' type.");
+
+ // Get the usefull part of the Node
+ Node child = result.getNodes().nextNode();
+ if (child == null || !child.isNodeType(NodeType.NT_RESOURCE))
+ throw new ArgeoException(
+ "ERROR: IN the current implemented model, '"
+ + NodeType.NT_FILE
+ + "' file node must have one and only one child of the nt:ressource, where actual data is stored");
+ return child;
+
+ } catch (RepositoryException re) {
+ throw new ArgeoException("Erreur while getting file node of ID "
+ + fileId, re);
+ }
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.utils;
+
+public class JcrUiUtils {
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.views;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
+import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
+import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
+import org.argeo.eclipse.ui.specific.FileHandler;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.RepositoryRegister;
+import org.argeo.jcr.ui.explorer.browser.NodeContentProvider;
+import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
+import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider;
+import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
+import org.argeo.jcr.ui.explorer.utils.JcrFileProvider;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+
+public class GenericJcrBrowser extends AbstractJcrBrowser {
+ private final static Log log = LogFactory.getLog(GenericJcrBrowser.class);
+
+ /* DEPENDENCY INJECTION */
+ private Session session;
+ private RepositoryRegister repositoryRegister;
+
+ // This page widgets
+ private TreeViewer nodesViewer;
+ private NodeContentProvider nodeContentProvider;
+ private TableViewer propertiesViewer;
+ private EventListener resultsObserver;
+
+ // Manage documents
+ private JcrFileProvider jcrFileProvider;
+ private FileHandler fileHandler;
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ // look for session
+ Session nodeSession = session;
+ if (nodeSession == null) {
+ Repository nodeRepository = JcrUtils.getRepositoryByAlias(
+ repositoryRegister, ArgeoJcrConstants.ALIAS_NODE);
+ if (nodeRepository != null)
+ try {
+ nodeSession = nodeRepository.login();
+ // TODO : enhance that to enable multirepository listener.
+ session = nodeSession;
+ } catch (RepositoryException e1) {
+ throw new ArgeoException("Cannot login to node repository");
+ }
+ }
+
+ // Instantiate the generic object that fits for
+ // both RCP & RAP
+ // Note that in RAP, it registers a service handler that provide the
+ // access to the files.
+ jcrFileProvider = new JcrFileProvider();
+ fileHandler = new FileHandler(jcrFileProvider);
+
+ parent.setLayout(new FillLayout());
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
+ sashForm.setSashWidth(4);
+ sashForm.setLayout(new FillLayout());
+
+ // Create the tree on top of the view
+ Composite top = new Composite(sashForm, SWT.NONE);
+ GridLayout gl = new GridLayout(1, false);
+ top.setLayout(gl);
+
+ nodeContentProvider = new NodeContentProvider(nodeSession,
+ repositoryRegister);
+
+ // nodes viewer
+ nodesViewer = createNodeViewer(top, nodeContentProvider);
+
+ // context menu
+ MenuManager menuManager = new MenuManager();
+ Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
+ nodesViewer.getTree().setMenu(menu);
+ getSite().registerContextMenu(menuManager, nodesViewer);
+ getSite().setSelectionProvider(nodesViewer);
+ nodesViewer.setInput(getViewSite());
+
+ // Create the property viewer on the bottom
+ Composite bottom = new Composite(sashForm, SWT.NONE);
+ bottom.setLayout(new GridLayout(1, false));
+ propertiesViewer = new TableViewer(bottom);
+ propertiesViewer.getTable().setLayoutData(
+ new GridData(SWT.FILL, SWT.FILL, true, true));
+ propertiesViewer.getTable().setHeaderVisible(true);
+ propertiesViewer.setContentProvider(new PropertiesContentProvider());
+ TableViewerColumn col = new TableViewerColumn(propertiesViewer,
+ SWT.NONE);
+ col.getColumn().setText("Name");
+ col.getColumn().setWidth(200);
+ col.setLabelProvider(new ColumnLabelProvider() {
+ public String getText(Object element) {
+ try {
+ return ((Property) element).getName();
+ } catch (RepositoryException e) {
+ throw new ArgeoException(
+ "Unexpected exception in label provider", e);
+ }
+ }
+ });
+ col = new TableViewerColumn(propertiesViewer, SWT.NONE);
+ col.getColumn().setText("Value");
+ col.getColumn().setWidth(400);
+ col.setLabelProvider(new ColumnLabelProvider() {
+ public String getText(Object element) {
+ try {
+ Property property = (Property) element;
+ if (property.getType() == PropertyType.BINARY)
+ return "<binary>";
+ else if (property.isMultiple())
+ return Arrays.asList(property.getValues()).toString();
+ else
+ return property.getValue().getString();
+ } catch (RepositoryException e) {
+ throw new ArgeoException(
+ "Unexpected exception in label provider", e);
+ }
+ }
+ });
+ col = new TableViewerColumn(propertiesViewer, SWT.NONE);
+ col.getColumn().setText("Type");
+ col.getColumn().setWidth(200);
+ col.setLabelProvider(new ColumnLabelProvider() {
+ public String getText(Object element) {
+ try {
+ return PropertyType.nameFromValue(((Property) element)
+ .getType());
+ } catch (RepositoryException e) {
+ throw new ArgeoException(
+ "Unexpected exception in label provider", e);
+ }
+ }
+ });
+ propertiesViewer.setInput(getViewSite());
+
+ sashForm.setWeights(getWeights());
+ nodesViewer.setComparer(new NodeViewerComparer());
+ }
+
+ /**
+ * To be overridden to adapt size of form and result frames.
+ */
+ protected int[] getWeights() {
+ return new int[] { 70, 30 };
+ }
+
+ // @Override
+ // public void setFocus() {
+ // nodesViewer.getTree().setFocus();
+ // }
+ //
+ // /*
+ // * NOTIFICATION
+ // */
+ // public void refresh(Object obj) {
+ // nodesViewer.refresh(obj);
+ // }
+ //
+ // public void nodeAdded(Node parentNode, Node newNode) {
+ // nodesViewer.refresh(parentNode);
+ // nodesViewer.expandToLevel(newNode, 0);
+ // }
+ //
+ // public void nodeRemoved(Node parentNode) {
+ //
+ // IStructuredSelection newSel = new StructuredSelection(parentNode);
+ // nodesViewer.setSelection(newSel, true);
+ // // Force refresh
+ // IStructuredSelection tmpSel = (IStructuredSelection) nodesViewer
+ // .getSelection();
+ // nodesViewer.refresh(tmpSel.getFirstElement());
+ // }
+
+ private JcrFileProvider getJcrFileProvider() {
+ return jcrFileProvider;
+ }
+
+ private FileHandler getFileHandler() {
+ return fileHandler;
+ }
+
+ protected TreeViewer createNodeViewer(Composite parent,
+ final ITreeContentProvider nodeContentProvider) {
+
+ final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
+
+ tmpNodeViewer.getTree().setLayoutData(
+ new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ tmpNodeViewer.setContentProvider(nodeContentProvider);
+ tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
+ tmpNodeViewer
+ .addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (!event.getSelection().isEmpty()) {
+ IStructuredSelection sel = (IStructuredSelection) event
+ .getSelection();
+ propertiesViewer.setInput(sel.getFirstElement());
+ } else {
+ propertiesViewer.setInput(getViewSite());
+ }
+ }
+ });
+
+ resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
+ try {
+ ObservationManager observationManager = session.getWorkspace()
+ .getObservationManager();
+ // FIXME Will not be notified if empty result is deleted
+ observationManager.addEventListener(resultsObserver,
+ Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/", true,
+ null, null, false);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot register listeners", e);
+ }
+
+ tmpNodeViewer
+ .addDoubleClickListener(new GenericNodeDoubleClickListener(
+ tmpNodeViewer));
+ return tmpNodeViewer;
+ }
+
+ @Override
+ protected TreeViewer getNodeViewer() {
+ return nodesViewer;
+ }
+
+ class TreeObserver extends AsyncUiEventListener {
+
+ public TreeObserver(Display display) {
+ super(display);
+ }
+
+ @Override
+ protected Boolean willProcessInUiThread(List<Event> events)
+ throws RepositoryException {
+ for (Event event : events) {
+ getLog().debug("Received event " + event);
+ String path = event.getPath();
+ int index = path.lastIndexOf('/');
+ String propertyName = path.substring(index + 1);
+ getLog().debug("Concerned property " + propertyName);
+ }
+ return false;
+ }
+
+ protected void onEventInUiThread(List<Event> events)
+ throws RepositoryException {
+ if (getLog().isTraceEnabled())
+ getLog().trace("Refresh result list");
+ nodesViewer.refresh();
+ }
+
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
+ this.repositoryRegister = repositoryRegister;
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.wizards;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+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.argeo.ArgeoException;
+import org.argeo.eclipse.ui.dialogs.Error;
+import org.argeo.eclipse.ui.specific.ImportToServerWizardPage;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.Wizard;
+
+public class ImportFileSystemWizard extends Wizard {
+ private final static Log log = LogFactory
+ .getLog(ImportFileSystemWizard.class);
+
+ private ImportToServerWizardPage importPage;
+ private final Node folder;
+
+ public ImportFileSystemWizard(Node folder) {
+ this.folder = folder;
+ setWindowTitle("Import from file system");
+ }
+
+ @Override
+ public void addPages() {
+ importPage = new ImportToServerWizardPage();
+ addPage(importPage);
+ setNeedsProgressMonitor(importPage.getNeedsProgressMonitor());
+ }
+
+ /**
+ * Called when the user click on 'Finish' in the wizard. The real upload to
+ * the JCR repository is done here.
+ */
+ @Override
+ public boolean performFinish() {
+
+ // Initialization
+ final String objectType = importPage.getObjectType();
+ final String objectPath = importPage.getObjectPath();
+
+ // We do not display a progress bar for one file only
+ if (importPage.FILE_ITEM_TYPE.equals(objectType)) {
+ // In Rap we must force the "real" upload of the file
+ importPage.performFinish();
+ try {
+ Node fileNode = folder.addNode(importPage.getObjectName(),
+ NodeType.NT_FILE);
+ Node resNode = fileNode.addNode(Property.JCR_CONTENT,
+ NodeType.NT_RESOURCE);
+ Binary binary = null;
+ try {
+ binary = folder.getSession().getValueFactory()
+ .createBinary(importPage.getFileInputStream());
+ resNode.setProperty(Property.JCR_DATA, binary);
+ } finally {
+ if (binary != null)
+ binary.dispose();
+ IOUtils.closeQuietly(importPage.getFileInputStream());
+ }
+ folder.getSession().save();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ } else if (importPage.FOLDER_ITEM_TYPE.equals(objectType)) {
+ if (objectPath == null || !new File(objectPath).exists()) {
+ Error.show("Directory " + objectPath + " does not exist");
+ return false;
+ }
+
+ Boolean failed = false;
+ final File dir = new File(objectPath).getAbsoluteFile();
+ final Long sizeB = directorySize(dir, 0l);
+ final Stats stats = new Stats();
+ Long begin = System.currentTimeMillis();
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ try {
+ Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB);
+ monitor.beginTask("", sizeKB);
+ importDirectory(folder, dir, monitor, stats);
+ monitor.done();
+ } catch (Exception e) {
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new ArgeoException("Cannot import "
+ + objectPath, e);
+ }
+ }
+ });
+ } catch (Exception e) {
+ Error.show("Cannot import " + objectPath, e);
+ failed = true;
+ }
+
+ Long duration = System.currentTimeMillis() - begin;
+ Long durationS = duration / 1000l;
+ String durationStr = (durationS / 60) + " min " + (durationS % 60)
+ + " s";
+ StringBuffer message = new StringBuffer("Imported\n");
+ message.append(stats.fileCount).append(" files\n");
+ message.append(stats.dirCount).append(" directories\n");
+ message.append(FileUtils.byteCountToDisplaySize(stats.sizeB));
+ if (failed)
+ message.append(" of planned ").append(
+ FileUtils.byteCountToDisplaySize(sizeB));
+ message.append("\n");
+ message.append("in ").append(durationStr).append("\n");
+ if (failed)
+ MessageDialog.openError(getShell(), "Import failed",
+ message.toString());
+ else
+ MessageDialog.openInformation(getShell(), "Import successful",
+ message.toString());
+
+ return true;
+ }
+ return false;
+
+ }
+
+ /** Recursively computes the size of the directory in bytes. */
+ protected Long directorySize(File dir, Long currentSize) {
+ Long size = currentSize;
+ File[] files = dir.listFiles();
+ for (File file : files) {
+ if (file.isDirectory()) {
+ size = directorySize(file, size);
+ } else {
+ size = size + file.length();
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Import recursively a directory and its content to the repository.
+ */
+ protected void importDirectory(Node folder, File dir,
+ IProgressMonitor monitor, Stats stats) {
+ try {
+ File[] files = dir.listFiles();
+ for (File file : files) {
+ if (file.isDirectory()) {
+ Node childFolder = folder.addNode(file.getName(),
+ NodeType.NT_FOLDER);
+ importDirectory(childFolder, file, monitor, stats);
+ folder.getSession().save();
+ stats.dirCount++;
+ } else {
+ Long fileSize = file.length();
+
+ // we skip tempory files that are created by apps when a
+ // file is being edited.
+ // TODO : make this configurable.
+ if (file.getName().lastIndexOf('~') != file.getName()
+ .length() - 1) {
+
+ monitor.subTask(file.getName() + " ("
+ + FileUtils.byteCountToDisplaySize(fileSize)
+ + ") " + file.getCanonicalPath());
+ try {
+ Node fileNode = folder.addNode(file.getName(),
+ NodeType.NT_FILE);
+ Node resNode = fileNode.addNode(
+ Property.JCR_CONTENT, NodeType.NT_RESOURCE);
+ Binary binary = null;
+ try {
+ binary = folder
+ .getSession()
+ .getValueFactory()
+ .createBinary(new FileInputStream(file));
+ resNode.setProperty(Property.JCR_DATA, binary);
+ } finally {
+ if (binary != null)
+ binary.dispose();
+ }
+ folder.getSession().save();
+ stats.fileCount++;
+ stats.sizeB = stats.sizeB + fileSize;
+ } catch (Exception e) {
+ log.warn("Import of "
+ + file
+ + " ("
+ + FileUtils
+ .byteCountToDisplaySize(fileSize)
+ + ") failed: " + e);
+ folder.getSession().refresh(false);
+ }
+ monitor.worked((int) (fileSize / FileUtils.ONE_KB));
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot import " + dir + " to " + folder,
+ e);
+ }
+ }
+
+ static class Stats {
+ public Long fileCount = 0l;
+ public Long dirCount = 0l;
+ public Long sizeB = 0l;
+ }
+}
--- /dev/null
+## English labels for Agreo JCR UI application
+
+## Generic labels
+nodeEditorLbl=Generic node editor
+genericNodePageTitle=Edit Node properties
+
+## Dummy ones
+testLbl=Internationalizations of messages seems to work properly.