"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(
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;
private ArtifactIndexer artifactIndexer = new ArtifactIndexer();
private JarFileIndexer jarFileIndexer = new JarFileIndexer();
+ private DistributionBundleIndexer distBundleIndexer = new DistributionBundleIndexer();
+
private PdeSourcesIndexer pdeSourceIndexer = new PdeSourcesIndexer(
artifactIndexer, jarFileIndexer);
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: "
+ 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 "
monitor.subTask(node.getName());
artifactIndexer.index(node);
jarFileIndexer.index(node);
+ distBundleIndexer.index(node);
node.getSession().save();
monitor.worked(1);
if (log.isDebugEnabled())
} finally {
JcrUtils.logoutQuietly(defaultSession);
}
-
}
WorkspaceEditorInput wei = new WorkspaceEditorInput(repoNodePath,
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;
s2 = e2.toString();
}
- if (e1 instanceof WorkspaceElem)
+ if (e1 instanceof WorkspaceElem || e1 instanceof ModularDistVersionElem)
// Reverse order for versions
return s2.compareTo(s1);
else
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;
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
--- /dev/null
+/*
+ * 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
--- /dev/null
+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
--- /dev/null
+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
package org.argeo.slc.client.ui.dist.model;
+import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
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) {
}
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) {
} 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();
}
}
}
-
+
@Override
public synchronized void dispose() {
- JcrUtils.logoutQuietly(defaultSession);
+ JcrUtils.logoutQuietly(currSession);
super.dispose();
}
}
--- /dev/null
+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;
+ }
+
+ }
+}
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);
}
}
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
// 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";
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";