]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Work in progress - work on modular distributions.
authorBruno Sinou <bsinou@argeo.org>
Thu, 6 Mar 2014 19:13:04 +0000 (19:13 +0000)
committerBruno Sinou <bsinou@argeo.org>
Thu, 6 Mar 2014 19:13:04 +0000 (19:13 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@6886 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

14 files changed:
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistImages.java
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/NormalizeWorkspace.java
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/OpenWorkspaceEditor.java
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/controllers/DistTreeComparator.java
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/controllers/DistTreeLabelProvider.java
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/editors/ModuleListPage.java [new file with mode: 0644]
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistBaseElem.java [new file with mode: 0644]
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistVersionElem.java [new file with mode: 0644]
plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/WorkspaceElem.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/DistributionBundleIndexer.java [new file with mode: 0644]
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoSync.java
runtime/org.argeo.slc.repo/src/main/resources/org/argeo/slc/repo/repo.cnd
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java

index e5c91fcd954e366a980b65bc02be036ef97e3c83..e54b93434c793b6677bbf7f137776a668ac421c9 100644 (file)
@@ -50,16 +50,21 @@ public class DistImages {
                        "icons/fetchRepo.png").createImage();
 
        /* DISTRIBUTIONS */
+       public final static Image IMG_WKSP_GROUP = DistPlugin.getImageDescriptor(
+                       "icons/wkspGroup.gif").createImage();
        public final static Image IMG_DISTGRP = DistPlugin.getImageDescriptor(
                        "icons/distGrp.gif").createImage();
        public final static Image IMG_DISTGRP_READONLY = DistPlugin
                        .getImageDescriptor("icons/distGrpReadOnly.gif").createImage();
 
+       public final static Image IMG_MODULAR_DIST_BASE = DistPlugin.getImageDescriptor(
+                       "icons/packages.gif").createImage();
+       public final static Image IMG_MODULAR_DIST_VERSION = DistPlugin.getImageDescriptor(
+                       "icons/packages.gif").createImage();
+
        public final static Image IMG_GROUP_BASE = DistPlugin.getImageDescriptor(
                        "icons/packages.gif").createImage();
 
-       public final static Image IMG_WKSP_GROUP = DistPlugin.getImageDescriptor(
-                       "icons/wkspGroup.gif").createImage();
 
        /* CHECK BOXES */
        public final static Image CHECKED = DistPlugin.getImageDescriptor(
index f6f9d06fea52412651de0080c99545ec112a8271..77cb0821202d9be79266c38e35e927c18528a7dd 100644 (file)
@@ -36,6 +36,7 @@ import org.argeo.slc.SlcException;
 import org.argeo.slc.client.ui.dist.DistPlugin;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.repo.ArtifactIndexer;
+import org.argeo.slc.repo.DistributionBundleIndexer;
 import org.argeo.slc.repo.JarFileIndexer;
 import org.argeo.slc.repo.PdeSourcesIndexer;
 import org.argeo.slc.repo.RepoConstants;
@@ -75,6 +76,8 @@ public class NormalizeWorkspace extends AbstractHandler implements SlcNames {
 
        private ArtifactIndexer artifactIndexer = new ArtifactIndexer();
        private JarFileIndexer jarFileIndexer = new JarFileIndexer();
+       private DistributionBundleIndexer distBundleIndexer = new DistributionBundleIndexer();
+
        private PdeSourcesIndexer pdeSourceIndexer = new PdeSourcesIndexer(
                        artifactIndexer, jarFileIndexer);
 
@@ -85,7 +88,8 @@ public class NormalizeWorkspace extends AbstractHandler implements SlcNames {
                Session currSession = null;
                NormalizeJob job;
                try {
-                       String msg = "Your are about to normalize workspace: " + wkspName
+                       String msg = "Your are about to normalize workspace: "
+                                       + wkspName
                                        + ".\nThis will index OSGi bundles and Maven artifacts, "
                                        + "it will also convert Maven sources to PDE Sources if needed.\n"
                                        + "Note that no information will be overwritten: "
@@ -139,7 +143,8 @@ public class NormalizeWorkspace extends AbstractHandler implements SlcNames {
                                                + session.getWorkspace().getName(),
                                                expectedCount.intValue());
                                NormalizingTraverser tiv = new NormalizingTraverser(monitor);
-                               session.getNode(artifactBasePath).accept(tiv);
+                               Node artifactBaseNode =session.getNode(artifactBasePath); 
+                               artifactBaseNode.accept(tiv);
                        } catch (Exception e) {
                                return new Status(IStatus.ERROR, DistPlugin.ID,
                                                "Cannot normalize distribution "
@@ -181,6 +186,7 @@ public class NormalizeWorkspace extends AbstractHandler implements SlcNames {
                                                        monitor.subTask(node.getName());
                                                        artifactIndexer.index(node);
                                                        jarFileIndexer.index(node);
+                                                       distBundleIndexer.index(node);
                                                        node.getSession().save();
                                                        monitor.worked(1);
                                                        if (log.isDebugEnabled())
index db7155efaaf01039f21c841a3e0188b6d3a8b35f..c7734a8c47f260e81106754f98840d7f8ea8a09a 100644 (file)
@@ -75,7 +75,6 @@ public class OpenWorkspaceEditor extends AbstractHandler {
                        } finally {
                                JcrUtils.logoutQuietly(defaultSession);
                        }
-
                }
 
                WorkspaceEditorInput wei = new WorkspaceEditorInput(repoNodePath,
index d0c7066d1fd82f0118024f68bbb98c4b8377e8a1..c5b17e089266ee529756a9cc8dddd611661595c0 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.slc.client.ui.dist.controllers;
 
 import org.argeo.slc.client.ui.dist.model.DistParentElem;
+import org.argeo.slc.client.ui.dist.model.ModularDistVersionElem;
 import org.argeo.slc.client.ui.dist.model.RepoElem;
 import org.argeo.slc.client.ui.dist.model.WkspGroupElem;
 import org.argeo.slc.client.ui.dist.model.WorkspaceElem;
@@ -43,7 +44,7 @@ public class DistTreeComparator extends ViewerComparator {
                        s2 = e2.toString();
                }
 
-               if (e1 instanceof WorkspaceElem)
+               if (e1 instanceof WorkspaceElem || e1 instanceof ModularDistVersionElem)
                        // Reverse order for versions
                        return s2.compareTo(s1);
                else
index 4bebdda8895f6aaa1d2db5b742736049be11b9c6..3fc3aca081b1be2d4cd77fa40505ac7687ec12c7 100644 (file)
@@ -3,7 +3,8 @@ package org.argeo.slc.client.ui.dist.controllers;
 import org.argeo.eclipse.ui.jcr.JcrImages;
 import org.argeo.slc.client.ui.dist.DistImages;
 import org.argeo.slc.client.ui.dist.model.DistParentElem;
-import org.argeo.slc.client.ui.dist.model.GroupBaseElem;
+import org.argeo.slc.client.ui.dist.model.ModularDistBaseElem;
+import org.argeo.slc.client.ui.dist.model.ModularDistVersionElem;
 import org.argeo.slc.client.ui.dist.model.RepoElem;
 import org.argeo.slc.client.ui.dist.model.WkspGroupElem;
 import org.argeo.slc.client.ui.dist.model.WorkspaceElem;
@@ -39,8 +40,12 @@ public class DistTreeLabelProvider extends ColumnLabelProvider {
                                return JcrImages.WORKSPACE_DISCONNECTED;
                } else if (element instanceof WkspGroupElem)
                        return DistImages.IMG_WKSP_GROUP;
-               else if (element instanceof GroupBaseElem)
-                       return DistImages.IMG_GROUP_BASE;
+               // else if (element instanceof GroupBaseElem)
+               // return DistImages.IMG_GROUP_BASE;
+               else if (element instanceof ModularDistBaseElem)
+                       return DistImages.IMG_MODULAR_DIST_BASE;
+               else if (element instanceof ModularDistVersionElem)
+                       return DistImages.IMG_MODULAR_DIST_VERSION;
                return super.getImage(element);
        }
 }
\ No newline at end of file
diff --git a/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/editors/ModuleListPage.java b/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/editors/ModuleListPage.java
new file mode 100644 (file)
index 0000000..04fee41
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * 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.slc.client.ui.dist.editors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+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.DynamicOperand;
+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.ArgeoException;
+import org.argeo.eclipse.ui.utils.CommandUtils;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.client.ui.dist.DistConstants;
+import org.argeo.slc.client.ui.dist.DistImages;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.commands.DeleteArtifacts;
+import org.argeo.slc.client.ui.dist.utils.NodeViewerComparator;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.jcr.SlcTypes;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+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.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+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.events.SelectionListener;
+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.Menu;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+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;
+
+/**
+ * Show all modules contained in a given modular distribution as filter-able
+ * table
+ */
+public class ModuleListPage extends FormPage implements SlcNames {
+
+       final static String PAGE_ID = "ModuleListPage";
+
+       // Business Objects
+       private Node modularDistribution;
+
+       // This page widgets
+       private NodeViewerComparator comparator;
+       private TableViewer viewer;
+       private FormToolkit tk;
+       private Composite header;
+       private Text filterTxt;
+       private final static String FILTER_HELP_MSG = "Enter filter criterion separated by a space";
+
+       private Node moduleParent;
+
+       public ModuleListPage(FormEditor formEditor, String title,
+                       Node modularDistribution) {
+               super(formEditor, PAGE_ID, title);
+               this.modularDistribution = modularDistribution;
+       }
+
+       @Override
+       protected void createFormContent(IManagedForm managedForm) {
+               ScrolledForm form = managedForm.getForm();
+               tk = managedForm.getToolkit();
+
+               // Main Layout
+               GridLayout layout = new GridLayout(1, false);
+               Composite body = form.getBody();
+               body.setLayout(layout);
+               // Add the filter section
+               createFilterPart(body);
+               // Add the table
+               createTableViewer(body);
+
+               // Add a listener to enable custom resize process
+               form.addControlListener(new ControlListener() {
+                       // form.addListener(SWT.RESIZE, new Listener() does not work
+                       public void controlResized(ControlEvent e) {
+                               refreshLayout();
+                       }
+
+                       public void controlMoved(ControlEvent e) {
+                       }
+               });
+               refresh();
+       }
+
+       private void refresh() {
+               final List<Node> result = JcrUtils
+                               .nodeIteratorToList(listBundleArtifacts());
+               viewer.setInput(result);
+       }
+
+       /** Build repository request */
+       private NodeIterator listBundleArtifacts() {
+               try {
+                       Session session = modularDistribution.getSession();
+                       QueryManager queryManager = session.getWorkspace()
+                                       .getQueryManager();
+                       QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+                       Selector source = factory.selector(SlcTypes.SLC_MODULE_COORDINATES,
+                                       SlcTypes.SLC_MODULE_COORDINATES);
+
+                       // Create a dynamic operand for each property on which we want to
+                       // filter
+                       DynamicOperand catDO = factory.propertyValue(
+                                       source.getSelectorName(), SlcNames.SLC_MODULE_CATEGORY);
+                       DynamicOperand nameDO = factory.propertyValue(
+                                       source.getSelectorName(), SlcNames.SLC_MODULE_NAME);
+                       DynamicOperand versionDO = factory.propertyValue(
+                                       source.getSelectorName(), SlcNames.SLC_MODULE_VERSION);
+
+                       String path = modularDistribution.getPath() + "/"
+                                       + SlcNames.SLC_MODULES;
+
+                       // Default Constraint: correct children
+                       Constraint defaultC = factory.descendantNode(
+                                       source.getSelectorName(), path);
+
+                       String filter = filterTxt.getText();
+
+                       // Build constraints based the textArea content
+                       if (filter != null && !"".equals(filter.trim())) {
+                               // Parse the String
+                               String[] strs = filter.trim().split(" ");
+                               for (String token : strs) {
+                                       token = token.replace('*', '%');
+                                       StaticOperand so = factory.literal(session
+                                                       .getValueFactory().createValue("%" + token + "%"));
+
+                                       Constraint currC = factory.comparison(catDO,
+                                                       QueryObjectModelFactory.JCR_OPERATOR_LIKE, so);
+                                       currC = factory.or(currC, factory.comparison(versionDO,
+                                                       QueryObjectModelFactory.JCR_OPERATOR_LIKE, so));
+                                       currC = factory.or(currC, factory.comparison(nameDO,
+                                                       QueryObjectModelFactory.JCR_OPERATOR_LIKE, so));
+
+                                       defaultC = factory.and(defaultC, currC);
+                               }
+                       }
+
+                       QueryObjectModel query = factory.createQuery(source, defaultC,
+                                       null, null);
+                       QueryResult result = query.execute();
+                       return result.getNodes();
+               } catch (RepositoryException re) {
+                       throw new SlcException("Unable to refresh module list for node "
+                                       + modularDistribution, re);
+               }
+       }
+
+       private void createFilterPart(Composite parent) {
+               header = tk.createComposite(parent);
+               GridLayout layout = new GridLayout(2, false);
+               layout.marginWidth = layout.marginHeight = layout.verticalSpacing = 0;
+               layout.horizontalSpacing = 5;
+               header.setLayout(layout);
+               GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false);
+               header.setLayoutData(gd);
+
+               // Text Area to filter
+               filterTxt = tk.createText(header, "", SWT.BORDER | SWT.SINGLE
+                               | SWT.SEARCH | SWT.CANCEL);
+               filterTxt.setMessage(FILTER_HELP_MSG);
+               gd = new GridData(SWT.FILL, SWT.FILL, false, false);
+               gd.grabExcessHorizontalSpace = true;
+               filterTxt.setLayoutData(gd);
+               filterTxt.addModifyListener(new ModifyListener() {
+                       public void modifyText(ModifyEvent event) {
+                               refresh();
+                       }
+               });
+
+               Button resetBtn = tk.createButton(header, null, SWT.PUSH);
+               resetBtn.setImage(DistImages.IMG_REPO_READONLY);
+               resetBtn.addSelectionListener(new SelectionListener() {
+
+                       public void widgetSelected(SelectionEvent e) {
+                               resetFilter();
+                       }
+
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               });
+
+       }
+
+       private void resetFilter() {
+               filterTxt.setText("");
+               filterTxt.setMessage(FILTER_HELP_MSG);
+       }
+
+       private void createTableViewer(Composite parent) {
+               // helpers to enable sorting by column
+               List<String> propertiesList = new ArrayList<String>();
+               List<Integer> propertyTypesList = new ArrayList<Integer>();
+
+               // Define the TableViewer
+               viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
+                               | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+
+               // Name
+               TableViewerColumn col = new TableViewerColumn(viewer, SWT.NONE);
+               col.getColumn().setWidth(300);
+               col.getColumn().setText("Name");
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       @Override
+                       public String getText(Object element) {
+                               return JcrUtils.get((Node) element,
+                                               DistConstants.SLC_BUNDLE_NAME);
+                       }
+               });
+               col.getColumn().addSelectionListener(getSelectionAdapter(0));
+               propertiesList.add(DistConstants.SLC_BUNDLE_NAME);
+               propertyTypesList.add(PropertyType.STRING);
+
+               // Symbolic name
+               col = new TableViewerColumn(viewer, SWT.V_SCROLL);
+               col.getColumn().setWidth(300);
+               col.getColumn().setText("Symbolic Name");
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       @Override
+                       public String getText(Object element) {
+                               return JcrUtils.get((Node) element, SLC_SYMBOLIC_NAME);
+                       }
+               });
+               col.getColumn().addSelectionListener(getSelectionAdapter(1));
+               propertiesList.add(SLC_SYMBOLIC_NAME);
+               propertyTypesList.add(PropertyType.STRING);
+
+               // Version
+               col = new TableViewerColumn(viewer, SWT.NONE);
+               col.getColumn().setWidth(130);
+               col.getColumn().setText("Version");
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       @Override
+                       public String getText(Object element) {
+                               return JcrUtils.get((Node) element, SLC_BUNDLE_VERSION);
+                       }
+               });
+               col.getColumn().addSelectionListener(getSelectionAdapter(2));
+               propertiesList.add(SLC_BUNDLE_VERSION);
+               propertyTypesList.add(PropertyType.STRING);
+
+               final Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+
+               viewer.setContentProvider(new DistributionsContentProvider());
+               getSite().setSelectionProvider(viewer);
+
+               comparator = new NodeViewerComparator(2,
+                               NodeViewerComparator.ASCENDING, propertiesList,
+                               propertyTypesList);
+               viewer.setComparator(comparator);
+
+               // Context Menu
+               MenuManager menuManager = new MenuManager();
+               Menu menu = menuManager.createContextMenu(viewer.getTable());
+               menuManager.addMenuListener(new IMenuListener() {
+                       public void menuAboutToShow(IMenuManager manager) {
+                               contextMenuAboutToShow(manager);
+                       }
+               });
+               viewer.getTable().setMenu(menu);
+               getSite().registerContextMenu(menuManager, viewer);
+
+               // Double click
+               viewer.addDoubleClickListener(new DoubleClickListener());
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTable().setFocus();
+       }
+
+       /** Programmatically configure the context menu */
+       protected void contextMenuAboutToShow(IMenuManager menuManager) {
+               IWorkbenchWindow window = DistPlugin.getDefault().getWorkbench()
+                               .getActiveWorkbenchWindow();
+               // Build conditions
+               // Delete selected artifacts
+               CommandUtils.refreshCommand(menuManager, window, DeleteArtifacts.ID,
+                               DeleteArtifacts.DEFAULT_LABEL, DeleteArtifacts.DEFAULT_ICON,
+                               true);
+       }
+
+       private SelectionAdapter getSelectionAdapter(final int index) {
+               SelectionAdapter selectionAdapter = new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               Table table = viewer.getTable();
+                               comparator.setColumn(index);
+                               int dir = table.getSortDirection();
+                               if (table.getSortColumn() == table.getColumn(index)) {
+                                       dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+                               } else {
+                                       dir = SWT.DOWN;
+                               }
+                               table.setSortDirection(dir);
+                               table.setSortColumn(table.getColumn(index));
+                               viewer.refresh();
+                       }
+               };
+               return selectionAdapter;
+       }
+
+       /* LOCAL CLASSES */
+       private class DistributionsContentProvider implements
+                       IStructuredContentProvider {
+               // we keep a cache of the Nodes in the content provider to be able to
+               // manage long request
+               private List<Node> nodes;
+
+               public void dispose() {
+               }
+
+               // We expect a list of nodes as a new input
+               @SuppressWarnings("unchecked")
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       nodes = (List<Node>) newInput;
+               }
+
+               public Object[] getElements(Object arg0) {
+                       return nodes.toArray();
+               }
+       }
+
+       private class DoubleClickListener implements IDoubleClickListener {
+
+               public void doubleClick(DoubleClickEvent event) {
+                       Object obj = ((IStructuredSelection) event.getSelection())
+                                       .getFirstElement();
+                       try {
+                               if (obj instanceof Node) {
+                                       Node node = (Node) obj;
+                                       if (node.isNodeType(SlcTypes.SLC_BUNDLE_ARTIFACT)) {
+                                               GenericBundleEditorInput gaei = new GenericBundleEditorInput(
+                                                               node);
+                                               DistPlugin.getDefault().getWorkbench()
+                                                               .getActiveWorkbenchWindow().getActivePage()
+                                                               .openEditor(gaei, GenericBundleEditor.ID);
+                                       }
+                               }
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Repository error while getting node info", re);
+                       } catch (PartInitException pie) {
+                               throw new ArgeoException(
+                                               "Unexepected exception while opening artifact editor",
+                                               pie);
+                       }
+               }
+       }
+
+       /**
+        * UI Trick to put scroll bar on the table rather than on the scrollform
+        */
+       private void refreshLayout() {
+               // Compute desired table size
+               int maxH = getManagedForm().getForm().getSize().y;
+               int maxW = getManagedForm().getForm().getParent().getSize().x;
+               maxH = maxH - header.getSize().y;
+               final Table table = viewer.getTable();
+               GridData gd = new GridData(SWT.LEFT, SWT.TOP, true, true);
+
+               // when table height is less than 200 px, we let the scroll bar on the
+               // scrollForm
+               // FIXME substract some spare space. There is room here for optimization
+               gd.heightHint = Math.max(maxH - 35, 200);
+               gd.widthHint = Math.max(maxW - 35, 200);
+
+               table.setLayoutData(gd);
+               getManagedForm().reflow(true);
+       }
+
+       @Override
+       public void setActive(boolean active) {
+               super.setActive(active);
+               if (active) {
+                       refreshLayout();
+               }
+       }
+}
\ No newline at end of file
diff --git a/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistBaseElem.java b/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistBaseElem.java
new file mode 100644 (file)
index 0000000..08c7d6d
--- /dev/null
@@ -0,0 +1,103 @@
+package org.argeo.slc.client.ui.dist.model;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.QueryObjectModel;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+import javax.jcr.query.qom.Selector;
+
+import org.argeo.ArgeoException;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.jcr.SlcTypes;
+
+/**
+ * Abstract the base a given modular distribution set that is the parent all
+ * versions of the same distribution
+ */
+public class ModularDistBaseElem extends DistParentElem {
+
+       final static public String AETHER_BINARIES_TYPE = "binaries";
+       final static public String AETHER_DEP_TYPE = "dep";
+       private String type;
+       private Node artifactBase;
+
+       public ModularDistBaseElem(WorkspaceElem wkspElem, String name,
+                       Node artifactBase, String type) {
+               super(name, wkspElem.inHome(), wkspElem.isReadOnly());
+               setParent(wkspElem);
+               this.artifactBase = artifactBase;
+               this.type = type;
+       }
+
+       /**
+        * Override normal behavior to initialize children only when first requested
+        */
+       @Override
+       public synchronized boolean hasChildren() {
+               if (isLoaded()) {
+                       return super.hasChildren();
+               } else {
+                       return true;
+               }
+       };
+
+       /**
+        * Override normal behavior to initialize children only when first requested
+        */
+       @Override
+       public synchronized Object[] getChildren() {
+               if (isLoaded()) {
+                       return super.getChildren();
+               } else {
+                       // initialize current object
+                       try {
+                               NodeIterator ni = getDistVersions();
+                               while (ni.hasNext()) {
+                                       Node curNode = ni.nextNode();
+                                       addChild(new ModularDistVersionElem(this, curNode
+                                                       .getProperty(SlcNames.SLC_ARTIFACT_VERSION)
+                                                       .getString(), curNode));
+                               }
+                               return super.getChildren();
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Unexcpected error while initializing children SingleJcrNode",
+                                               re);
+                       }
+               }
+       }
+
+       public NodeIterator getDistVersions() {
+               try {
+                       QueryManager queryManager = artifactBase.getSession()
+                                       .getWorkspace().getQueryManager();
+                       QueryObjectModelFactory factory = queryManager.getQOMFactory();
+                       Selector source = factory.selector(
+                                       SlcTypes.SLC_MODULAR_DISTRIBUTION,
+                                       SlcTypes.SLC_MODULAR_DISTRIBUTION);
+                       Constraint constraint = factory.descendantNode(
+                                       source.getSelectorName(), artifactBase.getPath());
+                       // Ordering order = factory.descending(factory.propertyValue(
+                       // source.getSelectorName(), SlcNames.SLC_ARTIFACT_VERSION));
+                       // Ordering[] orderings = { order };
+                       QueryObjectModel query = factory.createQuery(source, constraint,
+                                       null, null);
+                       QueryResult queryResult = query.execute();
+                       return queryResult.getNodes();
+               } catch (RepositoryException e) {
+                       throw new SlcException(
+                                       "Unable to version for modular distribution: " + getName(),
+                                       e);
+               }
+       }
+
+       public String getType() {
+               return type;
+       }
+
+}
\ No newline at end of file
diff --git a/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistVersionElem.java b/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/model/ModularDistVersionElem.java
new file mode 100644 (file)
index 0000000..8199f69
--- /dev/null
@@ -0,0 +1,31 @@
+package org.argeo.slc.client.ui.dist.model;
+
+import javax.jcr.Node;
+
+/**
+ * Abstract a node of type slc:modularDistribution that has a child node that
+ * lists the modules contained in the current distribution
+ */
+public class ModularDistVersionElem extends DistParentElem {
+       private final Node modularDistVersionNode;
+
+       public ModularDistVersionElem(ModularDistBaseElem modularDistGroupElem,
+                       String version, Node modularDistVersionNode) {
+               super(version, modularDistGroupElem.inHome(), modularDistGroupElem
+                               .isReadOnly());
+               setParent(modularDistGroupElem);
+               this.modularDistVersionNode = modularDistVersionNode;
+       }
+
+       public Object[] getChildren() {
+               return null;
+       }
+
+       public String getLabel() {
+               return getName();
+       }
+
+       public Node getModularDistVersionNode() {
+               return modularDistVersionNode;
+       }
+}
\ No newline at end of file
index 7cdccfc7a4436def5beb197993a766888ef0f481..41ba6efe32fa6dd51d3a3b14e7732381652b4c48 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.slc.client.ui.dist.model;
 
+import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -14,7 +15,7 @@ import org.argeo.slc.jcr.SlcTypes;
 public class WorkspaceElem extends DistParentElem {
        private final RepoElem repoElem;
        private String workspaceName;
-       private Session defaultSession;
+       private Session currSession;
 
        public WorkspaceElem(WkspGroupElem parent, RepoElem repoElem,
                        String workspaceName) {
@@ -33,20 +34,20 @@ public class WorkspaceElem extends DistParentElem {
        }
 
        public Boolean isConnected() {
-               if (defaultSession != null && defaultSession.isLive())
+               if (currSession != null && currSession.isLive())
                        return true;
                else
                        return false;
        }
 
        public void login() {
-               defaultSession = repoElem.repositoryLogin(getName());
+               currSession = repoElem.repositoryLogin(getName());
        }
 
        public boolean hasChildren() {
                try {
                        if (isConnected())
-                               return defaultSession.getRootNode().hasNodes();
+                               return currSession.getRootNode().hasNodes();
                        else
                                return false;
                } catch (RepositoryException re) {
@@ -64,23 +65,44 @@ public class WorkspaceElem extends DistParentElem {
                } else {
                        // initialize current object
                        try {
-                               if (defaultSession == null)
+                               if (currSession == null)
                                        return null;
                                else {
-                                       Query groupQuery = defaultSession
-                                                       .getWorkspace()
+                                       Query groupQuery = currSession.getWorkspace()
                                                        .getQueryManager()
+                                                       // .createQuery(
+                                                       // "select * from [" + SlcTypes.SLC_GROUP_BASE
+                                                       // + "] as group order by group.["
+                                                       // + SlcNames.SLC_GROUP_BASE_ID + "]",
                                                        .createQuery(
-                                                                       "select * from [" + SlcTypes.SLC_GROUP_BASE
-                                                                                       + "] as group order by group.["
-                                                                                       + SlcNames.SLC_GROUP_BASE_ID + "]",
-                                                                       Query.JCR_SQL2);
-                                       NodeIterator groups = groupQuery.execute().getNodes();
-                                       while (groups.hasNext()) {
-                                               addChild(new GroupBaseElem(WorkspaceElem.this, groups
-                                                               .nextNode()
-                                                               .getProperty(SlcNames.SLC_GROUP_BASE_ID)
-                                                               .getString()));
+                                                                       "select * from ["
+                                                                                       + SlcTypes.SLC_MODULAR_DISTRIBUTION
+                                                                                       + "]", Query.JCR_SQL2);
+                                       NodeIterator distributions = groupQuery.execute()
+                                                       .getNodes();
+                                       distribs: while (distributions.hasNext()) {
+                                               Node currDist = distributions.nextNode();
+                                               Node distBase = currDist.getParent().getParent();
+                                               if (!distBase.isNodeType(SlcTypes.SLC_ARTIFACT_BASE))
+                                                       continue distribs;
+                                               String groupId = distBase.getProperty(
+                                                               SlcNames.SLC_GROUP_ID).getString();
+                                               String artifactId = distBase.getProperty(
+                                                               SlcNames.SLC_ARTIFACT_ID).getString();
+
+                                               String name;
+                                               String type;
+                                               if (ModularDistBaseElem.AETHER_BINARIES_TYPE
+                                                               .equals(artifactId)) {
+                                                       name = groupId;
+                                                       type = ModularDistBaseElem.AETHER_BINARIES_TYPE;
+                                               } else {
+                                                       name = artifactId;
+                                                       type = ModularDistBaseElem.AETHER_DEP_TYPE;
+                                               }
+                                               if (getChildByName(name) == null)
+                                                       addChild(new ModularDistBaseElem(
+                                                                       WorkspaceElem.this, name, distBase, type));
                                        }
                                }
                                return super.getChildren();
@@ -91,10 +113,10 @@ public class WorkspaceElem extends DistParentElem {
                        }
                }
        }
-       
+
        @Override
        public synchronized void dispose() {
-               JcrUtils.logoutQuietly(defaultSession);
+               JcrUtils.logoutQuietly(currSession);
                super.dispose();
        }
 }
diff --git a/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/DistributionBundleIndexer.java b/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/DistributionBundleIndexer.java
new file mode 100644 (file)
index 0000000..7441490
--- /dev/null
@@ -0,0 +1,288 @@
+package org.argeo.slc.repo;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.aether.AetherUtils;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.jcr.SlcTypes;
+import org.osgi.framework.Constants;
+import org.sonatype.aether.artifact.Artifact;
+
+/**
+ * Index distribution bundles that is mainly dep artifacts that have generate a
+ * modular distribution csv index during maven build
+ */
+public class DistributionBundleIndexer implements NodeIndexer {
+       private final static Log log = LogFactory
+                       .getLog(DistributionBundleIndexer.class);
+
+       private final static String INDEX_FILE_NAME = "modularDistribution.csv";
+
+       // private final String url;
+
+       private Manifest manifest;
+       private String symbolicName;
+       private String version;
+
+       /** can be null */
+       // private String baseUrl;
+       /** can be null */
+       // private String relativeUrl;
+
+       private List<Artifact> artifacts;
+
+       private String separator = ",";
+
+       // public DistributionBundleIndexer(String url) {
+       // this.url = url;
+       // }
+       //
+       // public DistributionBundleIndexer(String baseUrl, String relativeUrl) {
+       // if (baseUrl == null || !baseUrl.endsWith("/"))
+       // throw new SlcException("Base url " + baseUrl + " badly formatted");
+       // if (relativeUrl.startsWith("http") || relativeUrl.startsWith("file:"))
+       // throw new SlcException("Relative URL " + relativeUrl
+       // + " badly formatted");
+       // this.url = baseUrl + relativeUrl;
+       // this.baseUrl = baseUrl;
+       // this.relativeUrl = relativeUrl;
+       // }
+
+       public Boolean support(String path) {
+               return FilenameUtils.getExtension(path).equals("jar");
+       }
+
+       public void index(Node fileNode) {
+               JarInputStream jarIn = null;
+               Binary fileBinary = null;
+               try {
+                       if (!support(fileNode.getPath()))
+                               return;
+
+                       if (!fileNode.isNodeType(NodeType.NT_FILE))
+                               return;
+
+                       Session jcrSession = fileNode.getSession();
+                       Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
+                       fileBinary = contentNode.getProperty(Property.JCR_DATA).getBinary();
+                       jarIn = new JarInputStream(fileBinary.getStream());
+
+                       // meta data
+                       manifest = jarIn.getManifest();
+                       if (manifest == null) {
+                               log.error(fileNode + " has no MANIFEST");
+                               return;
+                       }
+                       symbolicName = manifest.getMainAttributes().getValue(
+                                       Constants.BUNDLE_SYMBOLICNAME);
+                       version = manifest.getMainAttributes().getValue(
+                                       Constants.BUNDLE_VERSION);
+
+                       JarEntry indexEntry;
+                       while ((indexEntry = jarIn.getNextJarEntry()) != null) {
+                               String entryName = indexEntry.getName();
+                               if (entryName.equals(INDEX_FILE_NAME)) {
+                                       break;
+                               }
+                               jarIn.closeEntry();
+                       }
+
+                       // list artifacts
+                       if (indexEntry == null)
+                               return; // Not a modular definition artifact
+
+                       // throw new SlcException("No index " + INDEX_FILE_NAME + " in "
+                       // + fileNode.getPath());
+                       //
+
+                       artifacts = listArtifacts(jarIn);
+
+                       if (artifacts == null || artifacts.isEmpty())
+                               return; // no modules found
+                       else {
+                               Node modules;
+                               if (fileNode.isNodeType(SlcTypes.SLC_MODULAR_DISTRIBUTION)) {
+                                       modules = fileNode.getNode(SlcNames.SLC_MODULES);
+                               } else {
+                                       fileNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
+                                       modules = JcrUtils.mkdirs(fileNode, SlcNames.SLC_MODULES,
+                                                       NodeType.NT_UNSTRUCTURED);
+                               }
+
+                               for (Artifact artifact : artifacts) {
+                                       // TODO clean this once an overwrite policy has been
+                                       // decided.
+                                       if (!modules.hasNode(artifact.getArtifactId())) {
+                                               Node moduleCoord = modules.addNode(
+                                                               artifact.getArtifactId(),
+                                                               SlcTypes.SLC_MODULE_COORDINATES);
+                                               moduleCoord.setProperty(SlcNames.SLC_MODULE_NAME,
+                                                               artifact.getArtifactId());
+                                               moduleCoord.setProperty(SlcNames.SLC_MODULE_VERSION,
+                                                               artifact.getVersion());
+                                               String groupId = artifact.getGroupId();
+                                               if (groupId != null && !"".equals(groupId.trim()))
+                                                       moduleCoord.setProperty(
+                                                                       SlcNames.SLC_MODULE_CATEGORY,
+                                                                       artifact.getGroupId());
+                                       }
+                               }
+
+                       }
+
+                       jarIn.closeEntry();
+
+                       // find base URL
+                       // won't work if distribution artifact is not listed
+                       // for (int i = 0; i < artifacts.size(); i++) {
+                       // OsgiArtifact osgiArtifact = artifacts.get(i);
+                       // if (osgiArtifact.getSymbolicName().equals(symbolicName)
+                       // && osgiArtifact.getVersion().equals(version)) {
+                       // String relativeUrl = osgiArtifact.getRelativeUrl();
+                       // if (url.endsWith(relativeUrl)) {
+                       // baseUrl = url.substring(0, url.length()
+                       // - osgiArtifact.getRelativeUrl().length());
+                       // break;
+                       // }
+                       // }
+                       // }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot list dependencies from " + fileNode,
+                                       e);
+               } finally {
+                       if (jarIn != null)
+                               try {
+                                       jarIn.close();
+                               } catch (IOException e) {
+                                       // silent
+                               }
+               }
+       }
+
+       protected List<Artifact> listArtifacts(InputStream in) {
+               List<Artifact> artifacts = new ArrayList<Artifact>();
+               BufferedReader reader = null;
+               try {
+                       reader = new BufferedReader(new InputStreamReader(in));
+                       String line = null;
+                       while ((line = reader.readLine()) != null) {
+
+                               StringTokenizer st = new StringTokenizer(line, separator);
+                               String moduleName = st.nextToken();
+                               String moduleVersion = st.nextToken();
+                               String relativeUrl = st.nextToken();
+
+                               //
+                               // String Category = getCategoryFromRelativeUrl(relativeUrl,
+                               // moduleName);
+
+                               artifacts.add(AetherUtils.convertPathToArtifact(relativeUrl,
+                                               null));
+
+                               if (log.isTraceEnabled())
+                                       log.debug("Processed dependency: " + line);
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot list artifacts", e);
+               }
+               return artifacts;
+       }
+
+       /** Relative path to the directories where the files will be stored */
+       private String getCategoryFromRelativeUrl(String relativeUrl,
+                       String moduleName) {
+               int index = relativeUrl.indexOf("moduleName");
+               if (index < 1)
+                       throw new SlcException("Unvalid relative URL: " + relativeUrl
+                                       + " for module " + moduleName);
+               // Remove trailing /
+               String result = relativeUrl.substring(0, index - 1);
+               return result.replace('/', '.');
+       }
+
+       /**
+        * List full URLs of the bundles, based on base URL, usable directly for
+        * download.
+        */
+       // public List/* <String> */listUrls() {
+       // if (baseUrl == null)
+       // throw new SlcException("Base URL is not set");
+       //
+       // if (artifacts == null)
+       // throw new SlcException("Artifact list not initialized");
+       //
+       // List/* <String> */urls = new ArrayList();
+       // for (int i = 0; i < artifacts.size(); i++) {
+       // OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i);
+       // urls.add(baseUrl + osgiArtifact.getRelativeUrl());
+       // }
+       // return urls;
+       // }
+       //
+       // public void setBaseUrl(String baseUrl) {
+       // this.baseUrl = baseUrl;
+       // }
+
+       /** Separator used to parse the tabular file, default is "," */
+       public void setSeparator(String modulesUrlSeparator) {
+               this.separator = modulesUrlSeparator;
+       }
+
+       // public String getRelativeUrl() {
+       // return relativeUrl;
+       // }
+
+       /** One of the listed artifact */
+       protected static class OsgiArtifact {
+               private final String category;
+               private final String symbolicName;
+               private final String version;
+               private final String relativeUrl;
+
+               public OsgiArtifact(String category, String symbolicName,
+                               String version, String relativeUrl) {
+                       super();
+                       this.category = category;
+                       this.symbolicName = symbolicName;
+                       this.version = version;
+                       this.relativeUrl = relativeUrl;
+               }
+
+               public String getCategory() {
+                       return category;
+               }
+
+               public String getSymbolicName() {
+                       return symbolicName;
+               }
+
+               public String getVersion() {
+                       return version;
+               }
+
+               public String getRelativeUrl() {
+                       return relativeUrl;
+               }
+
+       }
+}
index 8d0147ec00c3259be9b0d608531fefc38ce3a30a..18e86492844a71e121d499d33a21e1877eadfa46 100644 (file)
@@ -262,78 +262,80 @@ public class RepoSync implements Runnable {
        protected void syncNode(Node sourceNode, Session targetSession)
                        throws RepositoryException, SAXException {
                // Boolean singleLevel = singleLevel(sourceNode);
+               try {
+                       if (monitor != null && monitor.isCanceled()) {
+                               updateMonitor("Fetched has been canceled, "
+                                               + "process is terminating");
+                               return;
+                       }
 
-               if (monitor != null && monitor.isCanceled()) {
-                       updateMonitor("Fetched has been canceled, "
-                                       + "process is terminating");
-                       return;
-               }
-
-               Node targetParentNode = targetSession.getNode(sourceNode.getParent()
-                               .getPath());
-               Node targetNode;
-               if (monitor != null
-                               && sourceNode.isNodeType(NodeType.NT_HIERARCHY_NODE))
-                       monitor.subTask("Process " + sourceNode.getPath());
-
-               final Boolean isNew;
-               if (!targetSession.itemExists(sourceNode.getPath())) {
-                       isNew = true;
-                       targetNode = targetParentNode.addNode(sourceNode.getName(),
-                                       sourceNode.getPrimaryNodeType().getName());
-               } else {
-                       isNew = false;
-                       targetNode = targetSession.getNode(sourceNode.getPath());
-                       if (!targetNode.getPrimaryNodeType().getName()
-                                       .equals(sourceNode.getPrimaryNodeType().getName()))
-                               targetNode.setPrimaryType(sourceNode.getPrimaryNodeType()
-                                               .getName());
-               }
+                       Node targetParentNode = targetSession.getNode(sourceNode
+                                       .getParent().getPath());
+                       Node targetNode;
+                       if (monitor != null
+                                       && sourceNode.isNodeType(NodeType.NT_HIERARCHY_NODE))
+                               monitor.subTask("Process " + sourceNode.getPath());
+
+                       final Boolean isNew;
+                       if (!targetSession.itemExists(sourceNode.getPath())) {
+                               isNew = true;
+                               targetNode = targetParentNode.addNode(sourceNode.getName(),
+                                               sourceNode.getPrimaryNodeType().getName());
+                       } else {
+                               isNew = false;
+                               targetNode = targetSession.getNode(sourceNode.getPath());
+                               if (!targetNode.getPrimaryNodeType().getName()
+                                               .equals(sourceNode.getPrimaryNodeType().getName()))
+                                       targetNode.setPrimaryType(sourceNode.getPrimaryNodeType()
+                                                       .getName());
+                       }
 
-               // export
-               // sourceNode.getSession().exportSystemView(sourceNode.getPath(),
-               // contentHandler, false, singleLevel);
-
-               // if (singleLevel) {
-               // if (targetSession.hasPendingChanges()) {
-               // // updateMonitor(
-               // // (isNew ? "Added " : "Updated ") + targetNode.getPath(),
-               // // true);
-               // if (doSave)
-               // targetSession.save();
-               // } else {
-               // // updateMonitor("Checked " + targetNode.getPath(), false);
-               // }
-               // }
-
-               // mixin and properties
-               for (NodeType nt : sourceNode.getMixinNodeTypes()) {
-                       if (!targetNode.isNodeType(nt.getName())
-                                       && targetNode.canAddMixin(nt.getName()))
-                               targetNode.addMixin(nt.getName());
-               }
-               copyProperties(sourceNode, targetNode);
+                       // export
+                       // sourceNode.getSession().exportSystemView(sourceNode.getPath(),
+                       // contentHandler, false, singleLevel);
+
+                       // if (singleLevel) {
+                       // if (targetSession.hasPendingChanges()) {
+                       // // updateMonitor(
+                       // // (isNew ? "Added " : "Updated ") + targetNode.getPath(),
+                       // // true);
+                       // if (doSave)
+                       // targetSession.save();
+                       // } else {
+                       // // updateMonitor("Checked " + targetNode.getPath(), false);
+                       // }
+                       // }
+
+                       // mixin and properties
+                       for (NodeType nt : sourceNode.getMixinNodeTypes()) {
+                               if (!targetNode.isNodeType(nt.getName())
+                                               && targetNode.canAddMixin(nt.getName()))
+                                       targetNode.addMixin(nt.getName());
+                       }
+                       copyProperties(sourceNode, targetNode);
 
-               // next level
-               for (NodeIterator ni = sourceNode.getNodes(); ni.hasNext();) {
-                       Node sourceChild = ni.nextNode();
-                       syncNode(sourceChild, targetSession);
-               }
+                       // next level
+                       for (NodeIterator ni = sourceNode.getNodes(); ni.hasNext();) {
+                               Node sourceChild = ni.nextNode();
+                               syncNode(sourceChild, targetSession);
+                       }
 
-               copyTimestamps(sourceNode, targetNode);
+                       copyTimestamps(sourceNode, targetNode);
 
-               if (sourceNode.isNodeType(NodeType.NT_HIERARCHY_NODE)) {
-                       if (targetSession.hasPendingChanges()) {
-                               if (sourceNode.isNodeType(NodeType.NT_FILE))
-                                       updateMonitor(
-                                                       (isNew ? "Added " : "Updated ")
-                                                                       + targetNode.getPath(), true);
-                               // if (doSave)
-                               targetSession.save();
-                       } else {
-                               if (sourceNode.isNodeType(NodeType.NT_FILE))
-                                       updateMonitor("Checked " + targetNode.getPath(), false);
+                       if (sourceNode.isNodeType(NodeType.NT_HIERARCHY_NODE)) {
+                               if (targetSession.hasPendingChanges()) {
+                                       if (sourceNode.isNodeType(NodeType.NT_FILE))
+                                               updateMonitor((isNew ? "Added " : "Updated ")
+                                                               + targetNode.getPath(), true);
+                                       // if (doSave)
+                                       targetSession.save();
+                               } else {
+                                       if (sourceNode.isNodeType(NodeType.NT_FILE))
+                                               updateMonitor("Checked " + targetNode.getPath(), false);
+                               }
                        }
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot sync source node " + sourceNode, e);
                }
        }
 
index c0bd681717562d3efcf191a13184766bb1ac248b..798046887e8cd1890b8959cd067708f49d675668 100644 (file)
@@ -30,6 +30,16 @@ mixin
 mixin
 + slc:artifactVersions (argeo:references) m
 
+[slc:modularDistribution]
+mixin
++ slc:modules (nt:unstructured) m
+
+[slc:moduleCoordinates] > nt:unstructured
+- slc:category (STRING)
+- slc:name (STRING)
+- slc:version (STRING)
+
+
 // ORIGINS
 [slc:knownOrigin] > nt:base
 mixin
index a728700ed9a1047816b483f5b5d41246f8a592dc..a68144a255e58f13d259ed4393034228011e6050 100644 (file)
@@ -115,6 +115,14 @@ public interface SlcNames {
        // slc:exportedPackage
        public final static String SLC_USES = "slc:uses";
 
+       // slc:modularDistribution
+       public final static String SLC_MODULES = "slc:modules";
+
+       // slc:moduleCoordinates
+       public final static String SLC_MODULE_CATEGORY = "slc:category";
+       public final static String SLC_MODULE_NAME = "slc:name";
+       public final static String SLC_MODULE_VERSION = "slc:version";
+
        // RPM
        // slc:rpm
        public final static String SLC_RPM_VERSION = "slc:rpmVersion";
index d53494cef390f37494947e3bdf8b7ff564a4cb7d..0d647af8d0f34db2f27db06cc0496c3a1e1c393e 100644 (file)
@@ -64,6 +64,9 @@ public interface SlcTypes {
        public final static String SLC_DYNAMIC_IMPORTED_PACKAGE = "slc:dynamicImportedPackage";
        public final static String SLC_REQUIRED_BUNDLE = "slc:requiredBundle";
        public final static String SLC_FRAGMENT_HOST = "slc:fragmentHost";
+       
+       public final static String SLC_MODULAR_DISTRIBUTION = "slc:modularDistribution";
+       public final static String SLC_MODULE_COORDINATES = "slc:moduleCoordinates";
 
        // origin
        public final static String SLC_KNOWN_ORIGIN = "slc:knownOrigin";