From: Mathieu Baudier Date: Sat, 15 Oct 2022 09:39:06 +0000 (+0200) Subject: Move JCR to another repository X-Git-Tag: v2.3.10~12 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=70566c6d66456ae2b8f7d3fe78be38d7d3701fc3 Move JCR to another repository --- diff --git a/.gitignore b/.gitignore index c306476f0..11caf4780 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,4 @@ **/bin/ -**/target/ -**/generated/ **/MANIFEST.MF -/build/ /sdk.mk /output/ diff --git a/Makefile b/Makefile index 791447698..406f96a56 100644 --- a/Makefile +++ b/Makefile @@ -28,8 +28,6 @@ swt/rap/org.argeo.swt.specific.rap \ swt/rap/org.argeo.cms.swt.rap \ swt/rap/org.argeo.cms.swt.rap.cli \ swt/rap/org.argeo.cms.e4.rap \ -jcr/org.argeo.cms.jcr \ -jcr/org.argeo.cms.jcr.ui \ DEP_CATEGORIES = \ org.argeo.tp \ @@ -39,7 +37,6 @@ osgi/api/org.argeo.tp.osgi \ osgi/equinox/org.argeo.tp.eclipse \ swt/rap/org.argeo.tp.swt \ swt/rap/org.argeo.tp.swt.workbench \ -org.argeo.tp.jcr \ $(A2_CATEGORY) \ swt/$(A2_CATEGORY) \ swt/rap/$(A2_CATEGORY) \ diff --git a/jcr/org.argeo.cms.jcr.ui/.classpath b/jcr/org.argeo.cms.jcr.ui/.classpath deleted file mode 100644 index 81fe078c2..000000000 --- a/jcr/org.argeo.cms.jcr.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/jcr/org.argeo.cms.jcr.ui/.project b/jcr/org.argeo.cms.jcr.ui/.project deleted file mode 100644 index 645296b6b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.cms.jcr.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/jcr/org.argeo.cms.jcr.ui/META-INF/.gitignore b/jcr/org.argeo.cms.jcr.ui/META-INF/.gitignore deleted file mode 100644 index 4854a41b9..000000000 --- a/jcr/org.argeo.cms.jcr.ui/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/jcr/org.argeo.cms.jcr.ui/bnd.bnd b/jcr/org.argeo.cms.jcr.ui/bnd.bnd deleted file mode 100644 index c3c609c70..000000000 --- a/jcr/org.argeo.cms.jcr.ui/bnd.bnd +++ /dev/null @@ -1,23 +0,0 @@ -Bundle-Activator: org.argeo.cms.ui.internal.Activator -Bundle-ActivationPolicy: lazy - -Import-Package: org.eclipse.swt,\ -org.eclipse.jface.window,\ -org.eclipse.core.commands,\ -javax.jcr.security,\ -org.eclipse.rap.fileupload;version="[2.1,4)",\ -org.eclipse.rap.rwt;version="[2.1,4)",\ -org.eclipse.rap.rwt.application;version="[2.1,4)",\ -org.eclipse.rap.rwt.client;version="[2.1,4)",\ -org.eclipse.rap.rwt.client.service;version="[2.1,4)",\ -org.eclipse.rap.rwt.service;version="[2.1,4)",\ -org.eclipse.rap.rwt.widgets;version="[2.1,4)",\ -org.osgi.*;version=0.0.0,\ -javax.servlet.*;version="[3,5)",\ -* - -## TODO: in order to enable single sourcing, we have introduced dummy RAP packages -# in the RCP specific bundle org.argeo.eclipse.ui.rap. -# this was working with RAP 2.x but since we upgrade Rap to 3.1.x, -# there is a version range issue cause org.argeo.eclipse.ui.rap bundle is still in 2.x -# We enable large RAP version range as a workaround that must be fixed \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/build.properties b/jcr/org.argeo.cms.jcr.ui/build.properties deleted file mode 100644 index c6baffa00..000000000 --- a/jcr/org.argeo.cms.jcr.ui/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - icons/ diff --git a/jcr/org.argeo.cms.jcr.ui/icons/loading.gif b/jcr/org.argeo.cms.jcr.ui/icons/loading.gif deleted file mode 100644 index 3288d1035..000000000 Binary files a/jcr/org.argeo.cms.jcr.ui/icons/loading.gif and /dev/null differ diff --git a/jcr/org.argeo.cms.jcr.ui/icons/noPic-goldenRatio-640px.png b/jcr/org.argeo.cms.jcr.ui/icons/noPic-goldenRatio-640px.png deleted file mode 100644 index 039650638..000000000 Binary files a/jcr/org.argeo.cms.jcr.ui/icons/noPic-goldenRatio-640px.png and /dev/null differ diff --git a/jcr/org.argeo.cms.jcr.ui/icons/noPic-square-640px.png b/jcr/org.argeo.cms.jcr.ui/icons/noPic-square-640px.png deleted file mode 100644 index 8e3abb518..000000000 Binary files a/jcr/org.argeo.cms.jcr.ui/icons/noPic-square-640px.png and /dev/null differ diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiConstants.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiConstants.java deleted file mode 100644 index fd1dda525..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiConstants.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.argeo.cms.ui; - -/** Commons constants */ -@Deprecated -public interface CmsUiConstants { - // DATAKEYS -// public final static String STYLE = EclipseUiConstants.CSS_CLASS; -// public final static String MARKUP = EclipseUiConstants.MARKUP_SUPPORT; - @Deprecated - /* RWT.CUSTOM_ITEM_HEIGHT */ - public final static String ITEM_HEIGHT = "org.eclipse.rap.rwt.customItemHeight"; - - // EVENT DETAILS - @Deprecated - /* RWT.HYPERLINK */ - public final static int HYPERLINK = 1 << 26; - - // STANDARD RESOURCES - public final static String LOADING_IMAGE = "icons/loading.gif"; - - // MISCEALLENEOUS - String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm"; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiProvider.java deleted file mode 100644 index 5f2377be5..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/CmsUiProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.argeo.cms.ui; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.acr.Content; -import org.argeo.cms.jcr.acr.JcrContent; -import org.argeo.cms.swt.acr.SwtUiProvider; -import org.argeo.jcr.JcrException; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** Stateless factory building an SWT user interface given a JCR context. */ -public interface CmsUiProvider extends SwtUiProvider { - /** - * Initialises a user interface. - * - * @param parent the parent composite - * @param context a context node (holding the JCR underlying session), or null - */ - default Control createUi(Composite parent, Node context) throws RepositoryException { - // does nothing by default - return null; - } - - default Control createUiPart(Composite parent, Node context) { - try { - return createUi(parent, context); - } catch (RepositoryException e) { - throw new JcrException("Cannot create UI for context " + context, e); - } - } - - @Override - default Control createUiPart(Composite parent, Content context) { - if (context == null) - return createUiPart(parent, (Node) null); - if (context instanceof JcrContent) { - Node node = ((JcrContent) context).getJcrNode(); - return createUiPart(parent, node); - } else { -// CmsLog.getLog(CmsUiProvider.class) -// .warn("In " + getClass() + ", content " + context + " is not compatible with JCR."); -// return createUiPart(parent, (Node) null); - - throw new IllegalArgumentException( - "In " + getClass() + ", content " + context + " is not compatible with JCR"); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/LifeCycleUiProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/LifeCycleUiProvider.java deleted file mode 100644 index 5d77c156c..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/LifeCycleUiProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.argeo.cms.ui; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -/** CmsUiProvider notified of initialisation with a system session. */ -public interface LifeCycleUiProvider extends CmsUiProvider { - public void init(Session adminSession) throws RepositoryException; - - public void destroy(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/AbstractFormPart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/AbstractFormPart.java deleted file mode 100644 index 4ce468826..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/AbstractFormPart.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; -/** - * AbstractFormPart implements IFormPart interface and can be used as a - * convenient base class for concrete form parts. If a method contains - * code that must be called, look for instructions to call 'super' - * when overriding. - * - * @see org.eclipse.ui.forms.widgets.Section - * @since 1.0 - */ -public abstract class AbstractFormPart implements IFormPart { - private IManagedForm managedForm; - private boolean dirty = false; - private boolean stale = true; - /** - * @see org.eclipse.ui.forms.IFormPart#initialize(org.eclipse.ui.forms.IManagedForm) - */ - public void initialize(IManagedForm form) { - this.managedForm = form; - } - /** - * Returns the form that manages this part. - * - * @return the managed form - */ - public IManagedForm getManagedForm() { - return managedForm; - } - /** - * Disposes the part. Subclasses should override to release any system - * resources. - */ - public void dispose() { - } - /** - * Commits the part. Subclasses should call 'super' when overriding. - * - * @param onSave - * true if the request to commit has arrived as a - * result of the 'save' action. - */ - public void commit(boolean onSave) { - dirty = false; - } - /** - * Sets the overall form input. Subclases may elect to override the method - * and adjust according to the form input. - * - * @param input - * the form input object - * @return false - */ - public boolean setFormInput(Object input) { - return false; - } - /** - * Instructs the part to grab keyboard focus. - */ - public void setFocus() { - } - /** - * Refreshes the section after becoming stale (falling behind data in the - * model). Subclasses must call 'super' when overriding this method. - */ - public void refresh() { - stale = false; - // since we have refreshed, any changes we had in the - // part are gone and we are not dirty - dirty = false; - } - /** - * Marks the part dirty. Subclasses should call this method as a result of - * user interaction with the widgets in the section. - */ - public void markDirty() { - dirty = true; - managedForm.dirtyStateChanged(); - } - /** - * Tests whether the part is dirty i.e. its widgets have state that is - * newer than the data in the model. - * - * @return true if the part is dirty, false - * otherwise. - */ - public boolean isDirty() { - return dirty; - } - /** - * Tests whether the part is stale i.e. its widgets have state that is - * older than the data in the model. - * - * @return true if the part is stale, false - * otherwise. - */ - public boolean isStale() { - return stale; - } - /** - * Marks the part stale. Subclasses should call this method as a result of - * model notification that indicates that the content of the section is no - * longer in sync with the model. - */ - public void markStale() { - stale = true; - managedForm.staleStateChanged(); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormColors.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormColors.java deleted file mode 100644 index 32b031b86..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormColors.java +++ /dev/null @@ -1,730 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.resource.LocalResourceManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.RGB; -//import org.eclipse.swt.internal.graphics.Graphics; -import org.eclipse.swt.widgets.Display; - -/** - * Manages colors that will be applied to forms and form widgets. The colors are - * chosen to make the widgets look correct in the editor area. If a different - * set of colors is needed, subclass this class and override 'initialize' and/or - * 'initializeColors'. - * - * @since 1.0 - */ -public class FormColors { - /** - * Key for the form title foreground color. - * - * @deprecated use IFormColors.TITLE. - */ - public static final String TITLE = IFormColors.TITLE; - - /** - * Key for the tree/table border color. - * - * @deprecated use IFormColors.BORDER - */ - public static final String BORDER = IFormColors.BORDER; - - /** - * Key for the section separator color. - * - * @deprecated use IFormColors.SEPARATOR. - */ - public static final String SEPARATOR = IFormColors.SEPARATOR; - - /** - * Key for the section title bar background. - * - * @deprecated use IFormColors.TB_BG - */ - public static final String TB_BG = IFormColors.TB_BG; - - /** - * Key for the section title bar foreground. - * - * @deprecated use IFormColors.TB_FG - */ - public static final String TB_FG = IFormColors.TB_FG; - - /** - * Key for the section title bar gradient. - * - * @deprecated use IFormColors.TB_GBG - */ - public static final String TB_GBG = IFormColors.TB_GBG; - - /** - * Key for the section title bar border. - * - * @deprecated use IFormColors.TB_BORDER. - */ - public static final String TB_BORDER = IFormColors.TB_BORDER; - - /** - * Key for the section toggle color. Since 3.1, this color is used for all - * section styles. - * - * @deprecated use IFormColors.TB_TOGGLE. - */ - public static final String TB_TOGGLE = IFormColors.TB_TOGGLE; - - /** - * Key for the section toggle hover color. - * - * @deprecated use IFormColors.TB_TOGGLE_HOVER. - */ - public static final String TB_TOGGLE_HOVER = IFormColors.TB_TOGGLE_HOVER; - - protected Map colorRegistry = new HashMap(10); - - private LocalResourceManager resources; - - protected Color background; - - protected Color foreground; - - private boolean shared; - - protected Display display; - - protected Color border; - - /** - * Creates form colors using the provided display. - * - * @param display - * the display to use - */ - public FormColors(Display display) { - this.display = display; - initialize(); - } - - /** - * Returns the display used to create colors. - * - * @return the display - */ - public Display getDisplay() { - return display; - } - - /** - * Initializes the colors. Subclasses can override this method to change the - * way colors are created. Alternatively, only the color table can be - * modified by overriding initializeColorTable(). - * - * @see #initializeColorTable - */ - protected void initialize() { - background = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); - foreground = display.getSystemColor(SWT.COLOR_LIST_FOREGROUND); - initializeColorTable(); - updateBorderColor(); - } - - /** - * Allocates colors for the following keys: BORDER, SEPARATOR and - * TITLE. Subclasses can override to allocate these colors differently. - */ - protected void initializeColorTable() { - createTitleColor(); - createColor(IFormColors.SEPARATOR, getColor(IFormColors.TITLE).getRGB()); - RGB black = getSystemColor(SWT.COLOR_BLACK); - RGB borderRGB = getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT); - createColor(IFormColors.BORDER, blend(borderRGB, black, 80)); - } - - /** - * Allocates colors for the section tool bar (all the keys that start with - * TB). Since these colors are only needed when TITLE_BAR style is used with - * the Section widget, they are not needed all the time and are allocated on - * demand. Consequently, this method will do nothing if the colors have been - * already initialized. Call this method prior to using colors with the TB - * keys to ensure they are available. - */ - public void initializeSectionToolBarColors() { - if (colorRegistry.containsKey(IFormColors.TB_BG)) - return; - createTitleBarGradientColors(); - createTitleBarOutlineColors(); - createTwistieColors(); - } - - /** - * Allocates additional colors for the form header, namely background - * gradients, bottom separator keylines and DND highlights. Since these - * colors are only needed for clients that want to use these particular - * style of header rendering, they are not needed all the time and are - * allocated on demand. Consequently, this method will do nothing if the - * colors have been already initialized. Call this method prior to using - * color keys with the H_ prefix to ensure they are available. - */ - protected void initializeFormHeaderColors() { - if (colorRegistry.containsKey(IFormColors.H_BOTTOM_KEYLINE2)) - return; - createFormHeaderColors(); - } - - /** - * Returns the RGB value of the system color represented by the code - * argument, as defined in SWT class. - * - * @param code - * the system color constant as defined in SWT - * class. - * @return the RGB value of the system color - */ - public RGB getSystemColor(int code) { - return getDisplay().getSystemColor(code).getRGB(); - } - - /** - * Creates the color for the specified key using the provided RGB object. - * The color object will be returned and also put into the registry. When - * the class is disposed, the color will be disposed with it. - * - * @param key - * the unique color key - * @param rgb - * the RGB object - * @return the allocated color object - */ - public Color createColor(String key, RGB rgb) { - // RAP [rh] changes due to missing Color constructor -// Color c = getResourceManager().createColor(rgb); -// Color prevC = (Color) colorRegistry.get(key); -// if (prevC != null && !prevC.isDisposed()) -// getResourceManager().destroyColor(prevC.getRGB()); -// Color c = Graphics.getColor(rgb); - Color c = new Color(display, rgb); - colorRegistry.put(key, c); - return c; - } - - /** - * Creates a color that can be used for areas of the form that is inactive. - * These areas can contain images, links, controls and other content but are - * considered auxilliary to the main content area. - * - *

- * The color should not be disposed because it is managed by this class. - * - * @return the inactive form color - */ - public Color getInactiveBackground() { - String key = "__ncbg__"; //$NON-NLS-1$ - Color color = getColor(key); - if (color == null) { - RGB sel = getSystemColor(SWT.COLOR_LIST_SELECTION); - // a blend of 95% white and 5% list selection system color - RGB ncbg = blend(sel, getSystemColor(SWT.COLOR_WHITE), 5); - color = createColor(key, ncbg); - } - return color; - } - - /** - * Creates the color for the specified key using the provided RGB values. - * The color object will be returned and also put into the registry. If - * there is already another color object under the same key in the registry, - * the existing object will be disposed. When the class is disposed, the - * color will be disposed with it. - * - * @param key - * the unique color key - * @param r - * red value - * @param g - * green value - * @param b - * blue value - * @return the allocated color object - */ - public Color createColor(String key, int r, int g, int b) { - return createColor(key, new RGB(r,g,b)); - } - - /** - * Computes the border color relative to the background. Allocated border - * color is designed to work well with white. Otherwise, stanard widget - * background color will be used. - */ - protected void updateBorderColor() { - if (isWhiteBackground()) - border = getColor(IFormColors.BORDER); - else { - border = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); - Color bg = getImpliedBackground(); - if (border.getRed() == bg.getRed() - && border.getGreen() == bg.getGreen() - && border.getBlue() == bg.getBlue()) - border = display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW); - } - } - - /** - * Sets the background color. All the toolkits that use this class will - * share the same background. - * - * @param bg - * background color - */ - public void setBackground(Color bg) { - this.background = bg; - updateBorderColor(); - updateFormHeaderColors(); - } - - /** - * Sets the foreground color. All the toolkits that use this class will - * share the same foreground. - * - * @param fg - * foreground color - */ - public void setForeground(Color fg) { - this.foreground = fg; - } - - /** - * Returns the current background color. - * - * @return the background color - */ - public Color getBackground() { - return background; - } - - /** - * Returns the current foreground color. - * - * @return the foreground color - */ - public Color getForeground() { - return foreground; - } - - /** - * Returns the computed border color. Border color depends on the background - * and is recomputed whenever the background changes. - * - * @return the current border color - */ - public Color getBorderColor() { - return border; - } - - /** - * Tests if the background is white. White background has RGB value - * 255,255,255. - * - * @return true if background is white, false - * otherwise. - */ - public boolean isWhiteBackground() { - Color bg = getImpliedBackground(); - return bg.getRed() == 255 && bg.getGreen() == 255 - && bg.getBlue() == 255; - } - - /** - * Returns the color object for the provided key or null if - * not in the registry. - * - * @param key - * the color key - * @return color object if found, or null if not. - */ - public Color getColor(String key) { - if (key.startsWith(IFormColors.TB_PREFIX)) - initializeSectionToolBarColors(); - else if (key.startsWith(IFormColors.H_PREFIX)) - initializeFormHeaderColors(); - return (Color) colorRegistry.get(key); - } - - /** - * Disposes all the colors in the registry. - */ - public void dispose() { - if (resources != null) - resources.dispose(); - resources = null; - colorRegistry = null; - } - - /** - * Marks the colors shared. This prevents toolkits that share this object - * from disposing it. - */ - public void markShared() { - this.shared = true; - } - - /** - * Tests if the colors are shared. - * - * @return true if shared, false otherwise. - */ - public boolean isShared() { - return shared; - } - - /** - * Blends c1 and c2 based in the provided ratio. - * - * @param c1 - * first color - * @param c2 - * second color - * @param ratio - * percentage of the first color in the blend (0-100) - * @return the RGB value of the blended color - */ - public static RGB blend(RGB c1, RGB c2, int ratio) { - int r = blend(c1.red, c2.red, ratio); - int g = blend(c1.green, c2.green, ratio); - int b = blend(c1.blue, c2.blue, ratio); - return new RGB(r, g, b); - } - - /** - * Tests the source RGB for range. - * - * @param rgb - * the tested RGB - * @param from - * range start (excluding the value itself) - * @param to - * range end (excluding the value itself) - * @return true if at least one of the primary colors in the - * source RGB are within the provided range, false - * otherwise. - */ - public static boolean testAnyPrimaryColor(RGB rgb, int from, int to) { - if (testPrimaryColor(rgb.red, from, to)) - return true; - if (testPrimaryColor(rgb.green, from, to)) - return true; - if (testPrimaryColor(rgb.blue, from, to)) - return true; - return false; - } - - /** - * Tests the source RGB for range. - * - * @param rgb - * the tested RGB - * @param from - * range start (excluding the value itself) - * @param to - * tange end (excluding the value itself) - * @return true if at least two of the primary colors in the - * source RGB are within the provided range, false - * otherwise. - */ - public static boolean testTwoPrimaryColors(RGB rgb, int from, int to) { - int total = 0; - if (testPrimaryColor(rgb.red, from, to)) - total++; - if (testPrimaryColor(rgb.green, from, to)) - total++; - if (testPrimaryColor(rgb.blue, from, to)) - total++; - return total >= 2; - } - - /** - * Blends two primary color components based on the provided ratio. - * - * @param v1 - * first component - * @param v2 - * second component - * @param ratio - * percentage of the first component in the blend - * @return - */ - private static int blend(int v1, int v2, int ratio) { - int b = (ratio * v1 + (100 - ratio) * v2) / 100; - return Math.min(255, b); - } - - private Color getImpliedBackground() { - if (getBackground() != null) - return getBackground(); - return getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); - } - - private static boolean testPrimaryColor(int value, int from, int to) { - return value > from && value < to; - } - - private void createTitleColor() { - /* - * RGB rgb = getSystemColor(SWT.COLOR_LIST_SELECTION); // test too light - * if (testTwoPrimaryColors(rgb, 120, 151)) rgb = blend(rgb, BLACK, 80); - * else if (testTwoPrimaryColors(rgb, 150, 256)) rgb = blend(rgb, BLACK, - * 50); createColor(TITLE, rgb); - */ - RGB bg = getImpliedBackground().getRGB(); - RGB listSelection = getSystemColor(SWT.COLOR_LIST_SELECTION); - RGB listForeground = getSystemColor(SWT.COLOR_LIST_FOREGROUND); - RGB rgb = listSelection; - - // Group 1 - // Rule: If at least 2 of the LIST_SELECTION RGB values are equal to or - // between 0 and 120, then use 100% LIST_SELECTION as it is (no - // additions) - // Examples: XP Default, Win Classic Standard, Win High Con White, Win - // Classic Marine - if (testTwoPrimaryColors(listSelection, -1, 121)) - rgb = listSelection; - // Group 2 - // When LIST_BACKGROUND = white (255, 255, 255) or not black, text - // colour = LIST_SELECTION @ 100% Opacity + 50% LIST_FOREGROUND over - // LIST_BACKGROUND - // Rule: If at least 2 of the LIST_SELECTION RGB values are equal to or - // between 121 and 255, then add 50% LIST_FOREGROUND to LIST_SELECTION - // foreground colour - // Examples: Win Vista, XP Silver, XP Olive , Win Classic Plum, OSX - // Aqua, OSX Graphite, Linux GTK - else if (testTwoPrimaryColors(listSelection, 120, 256) - || (bg.red == 0 && bg.green == 0 && bg.blue == 0)) - rgb = blend(listSelection, listForeground, 50); - // Group 3 - // When LIST_BACKGROUND = black (0, 0, 0), text colour = LIST_SELECTION - // @ 100% Opacity + 50% LIST_FOREGROUND over LIST_BACKGROUND - // Rule: If LIST_BACKGROUND = 0, 0, 0, then add 50% LIST_FOREGROUND to - // LIST_SELECTION foreground colour - // Examples: Win High Con Black, Win High Con #1, Win High Con #2 - // (covered in the second part of the OR clause above) - createColor(IFormColors.TITLE, rgb); - } - - private void createTwistieColors() { - RGB rgb = getColor(IFormColors.TITLE).getRGB(); - RGB white = getSystemColor(SWT.COLOR_WHITE); - createColor(TB_TOGGLE, rgb); - rgb = blend(rgb, white, 60); - createColor(TB_TOGGLE_HOVER, rgb); - } - - private void createTitleBarGradientColors() { - RGB tbBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND); - RGB bg = getImpliedBackground().getRGB(); - - // Group 1 - // Rule: If at least 2 of the RGB values are equal to or between 180 and - // 255, then apply specified opacity for Group 1 - // Examples: Vista, XP Silver, Wn High Con #2 - // Gradient Bottom = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - if (testTwoPrimaryColors(tbBg, 179, 256)) - tbBg = blend(tbBg, bg, 30); - - // Group 2 - // Rule: If at least 2 of the RGB values are equal to or between 121 and - // 179, then apply specified opacity for Group 2 - // Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black - // Gradient Bottom = TITLE_BACKGROUND @ 20% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - else if (testTwoPrimaryColors(tbBg, 120, 180)) - tbBg = blend(tbBg, bg, 20); - - // Group 3 - // Rule: Everything else - // Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX - // Aqua, Wn High Con White, Wn High Con #1 - // Gradient Bottom = TITLE_BACKGROUND @ 10% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - else { - tbBg = blend(tbBg, bg, 10); - } - - createColor(IFormColors.TB_BG, tbBg); - - // for backward compatibility - createColor(TB_GBG, tbBg); - } - - private void createTitleBarOutlineColors() { - // title bar outline - border color - RGB tbBorder = getSystemColor(SWT.COLOR_TITLE_BACKGROUND); - RGB bg = getImpliedBackground().getRGB(); - // Group 1 - // Rule: If at least 2 of the RGB values are equal to or between 180 and - // 255, then apply specified opacity for Group 1 - // Examples: Vista, XP Silver, Wn High Con #2 - // Keyline = TITLE_BACKGROUND @ 70% Opacity over LIST_BACKGROUND - if (testTwoPrimaryColors(tbBorder, 179, 256)) - tbBorder = blend(tbBorder, bg, 70); - - // Group 2 - // Rule: If at least 2 of the RGB values are equal to or between 121 and - // 179, then apply specified opacity for Group 2 - // Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black - - // Keyline = TITLE_BACKGROUND @ 50% Opacity over LIST_BACKGROUND - else if (testTwoPrimaryColors(tbBorder, 120, 180)) - tbBorder = blend(tbBorder, bg, 50); - - // Group 3 - // Rule: Everything else - // Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX - // Aqua, Wn High Con White, Wn High Con #1 - - // Keyline = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND - else { - tbBorder = blend(tbBorder, bg, 30); - } - createColor(FormColors.TB_BORDER, tbBorder); - } - - private void updateFormHeaderColors() { - if (colorRegistry.containsKey(IFormColors.H_GRADIENT_END)) { - disposeIfFound(IFormColors.H_GRADIENT_END); - disposeIfFound(IFormColors.H_GRADIENT_START); - disposeIfFound(IFormColors.H_BOTTOM_KEYLINE1); - disposeIfFound(IFormColors.H_BOTTOM_KEYLINE2); - disposeIfFound(IFormColors.H_HOVER_LIGHT); - disposeIfFound(IFormColors.H_HOVER_FULL); - initializeFormHeaderColors(); - } - } - - private void disposeIfFound(String key) { - Color color = getColor(key); - if (color != null) { - colorRegistry.remove(key); - // RAP [rh] changes due to missing Color#dispose() -// color.dispose(); - } - } - - private void createFormHeaderColors() { - createFormHeaderGradientColors(); - createFormHeaderKeylineColors(); - createFormHeaderDNDColors(); - } - - private void createFormHeaderGradientColors() { - RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND); - Color bgColor = getImpliedBackground(); - RGB bg = bgColor.getRGB(); - RGB bottom, top; - // Group 1 - // Rule: If at least 2 of the RGB values are equal to or between 180 and - // 255, then apply specified opacity for Group 1 - // Examples: Vista, XP Silver, Wn High Con #2 - // Gradient Bottom = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - if (testTwoPrimaryColors(titleBg, 179, 256)) { - bottom = blend(titleBg, bg, 30); - top = bg; - } - - // Group 2 - // Rule: If at least 2 of the RGB values are equal to or between 121 and - // 179, then apply specified opacity for Group 2 - // Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black - // Gradient Bottom = TITLE_BACKGROUND @ 20% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - else if (testTwoPrimaryColors(titleBg, 120, 180)) { - bottom = blend(titleBg, bg, 20); - top = bg; - } - - // Group 3 - // Rule: If at least 2 of the RGB values are equal to or between 0 and - // 120, then apply specified opacity for Group 3 - // Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX - // Aqua, Wn High Con White, Wn High Con #1 - // Gradient Bottom = TITLE_BACKGROUND @ 10% Opacity over LIST_BACKGROUND - // Gradient Top = TITLE BACKGROUND @ 0% Opacity over LIST_BACKGROUND - else { - bottom = blend(titleBg, bg, 10); - top = bg; - } - createColor(IFormColors.H_GRADIENT_END, top); - createColor(IFormColors.H_GRADIENT_START, bottom); - } - - private void createFormHeaderKeylineColors() { - RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND); - Color bgColor = getImpliedBackground(); - RGB bg = bgColor.getRGB(); - RGB keyline2; - // H_BOTTOM_KEYLINE1 - createColor(IFormColors.H_BOTTOM_KEYLINE1, new RGB(255, 255, 255)); - - // H_BOTTOM_KEYLINE2 - // Group 1 - // Rule: If at least 2 of the RGB values are equal to or between 180 and - // 255, then apply specified opacity for Group 1 - // Examples: Vista, XP Silver, Wn High Con #2 - // Keyline = TITLE_BACKGROUND @ 70% Opacity over LIST_BACKGROUND - if (testTwoPrimaryColors(titleBg, 179, 256)) - keyline2 = blend(titleBg, bg, 70); - - // Group 2 - // Rule: If at least 2 of the RGB values are equal to or between 121 and - // 179, then apply specified opacity for Group 2 - // Examples: XP Olive, OSX Graphite, Linux GTK, Wn High Con Black - // Keyline = TITLE_BACKGROUND @ 50% Opacity over LIST_BACKGROUND - else if (testTwoPrimaryColors(titleBg, 120, 180)) - keyline2 = blend(titleBg, bg, 50); - - // Group 3 - // Rule: If at least 2 of the RGB values are equal to or between 0 and - // 120, then apply specified opacity for Group 3 - // Examples: XP Default, Wn Classic Standard, Wn Marine, Wn Plum, OSX - // Aqua, Wn High Con White, Wn High Con #1 - - // Keyline = TITLE_BACKGROUND @ 30% Opacity over LIST_BACKGROUND - else - keyline2 = blend(titleBg, bg, 30); - // H_BOTTOM_KEYLINE2 - createColor(IFormColors.H_BOTTOM_KEYLINE2, keyline2); - } - - private void createFormHeaderDNDColors() { - RGB titleBg = getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT); - Color bgColor = getImpliedBackground(); - RGB bg = bgColor.getRGB(); - RGB light, full; - // ALL Themes - // - // Light Highlight - // When *near* the 'hot' area - // Rule: If near the title in the 'hot' area, show background highlight - // TITLE_BACKGROUND_GRADIENT @ 40% - light = blend(titleBg, bg, 40); - // Full Highlight - // When *on* the title area (regions 1 and 2) - // Rule: If near the title in the 'hot' area, show background highlight - // TITLE_BACKGROUND_GRADIENT @ 60% - full = blend(titleBg, bg, 60); - // H_DND_LIGHT - // H_DND_FULL - createColor(IFormColors.H_HOVER_LIGHT, light); - createColor(IFormColors.H_HOVER_FULL, full); - } - - private LocalResourceManager getResourceManager() { - if (resources == null) - resources = new LocalResourceManager(JFaceResources.getResources()); - return resources; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormFonts.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormFonts.java deleted file mode 100644 index 9e931ba50..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormFonts.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import java.util.HashMap; - -import org.eclipse.jface.resource.DeviceResourceException; -import org.eclipse.jface.resource.FontDescriptor; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.resource.LocalResourceManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Device; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -//import org.eclipse.swt.internal.graphics.Graphics; -import org.eclipse.swt.widgets.Display; - -public class FormFonts { - private static FormFonts instance; - - public static FormFonts getInstance() { - if (instance == null) - instance = new FormFonts(); - return instance; - } - - private LocalResourceManager resources; - private HashMap descriptors; - - private FormFonts() { - } - - private class BoldFontDescriptor extends FontDescriptor { - private FontData[] fFontData; - - BoldFontDescriptor(Font font) { - // RAP [if] Changes due to different way of creating fonts - // fFontData = font.getFontData(); - // for (int i = 0; i < fFontData.length; i++) { - // fFontData[i].setStyle(fFontData[i].getStyle() | SWT.BOLD); - // } - FontData fontData = font.getFontData()[0]; - // Font boldFont = Graphics.getFont( fontData.getName(), - // fontData.getHeight(), - // fontData.getStyle() | SWT.BOLD ); - Font boldFont = new Font(Display.getCurrent(), fontData.getName(), fontData.getHeight(), - fontData.getStyle() | SWT.BOLD); - fFontData = boldFont.getFontData(); - } - - public boolean equals(Object obj) { - if (obj instanceof BoldFontDescriptor) { - BoldFontDescriptor desc = (BoldFontDescriptor) obj; - if (desc.fFontData.length != fFontData.length) - return false; - for (int i = 0; i < fFontData.length; i++) - if (!fFontData[i].equals(desc.fFontData[i])) - return false; - return true; - } - return false; - } - - public int hashCode() { - int hash = 0; - for (int i = 0; i < fFontData.length; i++) - hash = hash * 7 + fFontData[i].hashCode(); - return hash; - } - - public Font createFont(Device device) throws DeviceResourceException { - // RAP [if] Changes due to different way of creating fonts - return new Font(device, fFontData[0]); - // return Graphics.getFont( fFontData[ 0 ] ); - } - - public void destroyFont(Font previouslyCreatedFont) { - // RAP [if] unnecessary - // previouslyCreatedFont.dispose(); - } - } - - public Font getBoldFont(Display display, Font font) { - checkHashMaps(); - BoldFontDescriptor desc = new BoldFontDescriptor(font); - Font result = getResourceManager().createFont(desc); - descriptors.put(result, desc); - return result; - } - - public boolean markFinished(Font boldFont) { - checkHashMaps(); - BoldFontDescriptor desc = (BoldFontDescriptor) descriptors.get(boldFont); - if (desc != null) { - getResourceManager().destroyFont(desc); - if (getResourceManager().find(desc) == null) { - descriptors.remove(boldFont); - validateHashMaps(); - } - return true; - - } - // if the image was not found, dispose of it for the caller - // RAP [if] unnecessary - // boldFont.dispose(); - return false; - } - - private LocalResourceManager getResourceManager() { - if (resources == null) - resources = new LocalResourceManager(JFaceResources.getResources()); - return resources; - } - - private void checkHashMaps() { - if (descriptors == null) - descriptors = new HashMap(); - } - - private void validateHashMaps() { - if (descriptors.size() == 0) - descriptors = null; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormToolkit.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormToolkit.java deleted file mode 100644 index 99271046a..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormToolkit.java +++ /dev/null @@ -1,913 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -//import org.eclipse.swt.custom.CCombo; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.events.FocusAdapter; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -// RAP [rh] Paint events missing -//import org.eclipse.swt.events.PaintEvent; -//import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -//RAP [rh] GC missing -//import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -//import org.eclipse.swt.graphics.RGB; -//import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -//import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -//import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.Widget; -//import org.eclipse.ui.forms.FormColors; -//import org.eclipse.ui.forms.HyperlinkGroup; -//import org.eclipse.ui.forms.IFormColors; -//import org.eclipse.ui.internal.forms.widgets.FormFonts; -//import org.eclipse.ui.internal.forms.widgets.FormUtil; - -/** - * The toolkit is responsible for creating SWT controls adapted to work in - * Eclipse forms. In addition to changing their presentation properties (fonts, - * colors etc.), various listeners are attached to make them behave correctly in - * the form context. - *

- * In addition to being the control factory, the toolkit is also responsible for - * painting flat borders for select controls, managing hyperlink groups and - * control colors. - *

- * The toolkit creates some of the most common controls used to populate Eclipse - * forms. Controls that must be created using their constructors, - * adapt() method is available to change its properties in the - * same way as with the supported toolkit controls. - *

- * Typically, one toolkit object is created per workbench part (for example, an - * editor or a form wizard). The toolkit is disposed when the part is disposed. - * To conserve resources, it is possible to create one color object for the - * entire plug-in and share it between several toolkits. The plug-in is - * responsible for disposing the colors (disposing the toolkit that uses shared - * color object will not dispose the colors). - *

- * FormToolkit is normally instantiated, but can also be subclassed if some of - * the methods needs to be modified. In those cases, super must - * be called to preserve normal behaviour. - * - * @since 1.0 - */ -public class FormToolkit { - public static final String KEY_DRAW_BORDER = "FormWidgetFactory.drawBorder"; //$NON-NLS-1$ - - public static final String TREE_BORDER = "treeBorder"; //$NON-NLS-1$ - - public static final String TEXT_BORDER = "textBorder"; //$NON-NLS-1$ - - private int borderStyle = SWT.NULL; - - private FormColors colors; - - private int orientation = Window.getDefaultOrientation(); - - // private KeyListener deleteListener; - // RAP [rh] Paint events missing -// private BorderPainter borderPainter; - - private BoldFontHolder boldFontHolder; - -// private HyperlinkGroup hyperlinkGroup; - - private boolean isDisposed = false; - - /* default */ - VisibilityHandler visibilityHandler; - - /* default */ - KeyboardHandler keyboardHandler; - - // RAP [rh] Paint events missing -// private class BorderPainter implements PaintListener { -// public void paintControl(PaintEvent event) { -// Composite composite = (Composite) event.widget; -// Control[] children = composite.getChildren(); -// for (int i = 0; i < children.length; i++) { -// Control c = children[i]; -// boolean inactiveBorder = false; -// boolean textBorder = false; -// if (!c.isVisible()) -// continue; -// /* -// * if (c.getEnabled() == false && !(c instanceof CCombo)) -// * continue; -// */ -// if (c instanceof Hyperlink) -// continue; -// Object flag = c.getData(KEY_DRAW_BORDER); -// if (flag != null) { -// if (flag.equals(Boolean.FALSE)) -// continue; -// if (flag.equals(TREE_BORDER)) -// inactiveBorder = true; -// else if (flag.equals(TEXT_BORDER)) -// textBorder = true; -// } -// if (getBorderStyle() == SWT.BORDER) { -// if (!inactiveBorder && !textBorder) { -// continue; -// } -// if (c instanceof Text || c instanceof Table -// || c instanceof Tree) -// continue; -// } -// if (!inactiveBorder -// && (c instanceof Text || c instanceof CCombo || textBorder)) { -// Rectangle b = c.getBounds(); -// GC gc = event.gc; -// gc.setForeground(c.getBackground()); -// gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1, -// b.height + 1); -// // gc.setForeground(getBorderStyle() == SWT.BORDER ? colors -// // .getBorderColor() : colors.getForeground()); -// gc.setForeground(colors.getBorderColor()); -// if (c instanceof CCombo) -// gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1, -// b.height + 1); -// else -// gc.drawRectangle(b.x - 1, b.y - 2, b.width + 1, -// b.height + 3); -// } else if (inactiveBorder || c instanceof Table -// || c instanceof Tree) { -// Rectangle b = c.getBounds(); -// GC gc = event.gc; -// gc.setForeground(colors.getBorderColor()); -// gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1, -// b.height + 1); -// } -// } -// } -// } - - private static class VisibilityHandler extends FocusAdapter { - public void focusGained(FocusEvent e) { - Widget w = e.widget; - if (w instanceof Control) { - FormUtil.ensureVisible((Control) w); - } - } - } - - private static class KeyboardHandler extends KeyAdapter { - public void keyPressed(KeyEvent e) { - Widget w = e.widget; - if (w instanceof Control) { - if (e.doit) - FormUtil.processKey(e.keyCode, (Control) w); - } - } - } - - private class BoldFontHolder { - private Font normalFont; - - private Font boldFont; - - public BoldFontHolder() { - } - - public Font getBoldFont(Font font) { - createBoldFont(font); - return boldFont; - } - - private void createBoldFont(Font font) { - if (normalFont == null || !normalFont.equals(font)) { - normalFont = font; - dispose(); - } - if (boldFont == null) { - boldFont = FormFonts.getInstance().getBoldFont(colors.getDisplay(), - normalFont); - } - } - - public void dispose() { - if (boldFont != null) { - FormFonts.getInstance().markFinished(boldFont); - boldFont = null; - } - } - } - - /** - * Creates a toolkit that is self-sufficient (will manage its own colors). - *

- * Clients that call this method must call {@link #dispose()} when they - * are finished using the toolkit. - * - */ - public FormToolkit(Display display) { - this(new FormColors(display)); - } - - /** - * Creates a toolkit that will use the provided (shared) colors. The toolkit - * will dispose the colors if and only if they are not marked as - * shared via the markShared() method. - *

- * Clients that call this method must call {@link #dispose()} when they - * are finished using the toolkit. - * - * @param colors - * the shared colors - */ - public FormToolkit(FormColors colors) { - this.colors = colors; - initialize(); - } - - /** - * Creates a button as a part of the form. - * - * @param parent - * the button parent - * @param text - * an optional text for the button (can be null) - * @param style - * the button style (for example, SWT.PUSH) - * @return the button widget - */ - public Button createButton(Composite parent, String text, int style) { - Button button = new Button(parent, style | SWT.FLAT | orientation); - if (text != null) - button.setText(text); - adapt(button, true, true); - return button; - } - - /** - * Creates the composite as a part of the form. - * - * @param parent - * the composite parent - * @return the composite widget - */ - public Composite createComposite(Composite parent) { - return createComposite(parent, SWT.NULL); - } - - /** - * Creates the composite as part of the form using the provided style. - * - * @param parent - * the composite parent - * @param style - * the composite style - * @return the composite widget - */ - public Composite createComposite(Composite parent, int style) { -// Composite composite = new LayoutComposite(parent, style | orientation); - Composite composite = new Composite(parent, style | orientation); - adapt(composite); - return composite; - } - - /** - * Creats the composite that can server as a separator between various parts - * of a form. Separator height should be controlled by setting the height - * hint on the layout data for the composite. - * - * @param parent - * the separator parent - * @return the separator widget - */ -// RAP [rh] createCompositeSeparator: currently no useful implementation possible, delete? - public Composite createCompositeSeparator(Composite parent) { - final Composite composite = new Composite(parent, orientation); -// RAP [rh] GC and paint events missing -// composite.addListener(SWT.Paint, new Listener() { -// public void handleEvent(Event e) { -// if (composite.isDisposed()) -// return; -// Rectangle bounds = composite.getBounds(); -// GC gc = e.gc; -// gc.setForeground(colors.getColor(IFormColors.SEPARATOR)); -// if (colors.getBackground() != null) -// gc.setBackground(colors.getBackground()); -// gc.fillGradientRectangle(0, 0, bounds.width, bounds.height, -// false); -// } -// }); -// if (parent instanceof Section) -// ((Section) parent).setSeparatorControl(composite); - return composite; - } - - /** - * Creates a label as a part of the form. - * - * @param parent - * the label parent - * @param text - * the label text - * @return the label widget - */ - public Label createLabel(Composite parent, String text) { - return createLabel(parent, text, SWT.NONE); - } - - /** - * Creates a label as a part of the form. - * - * @param parent - * the label parent - * @param text - * the label text - * @param style - * the label style - * @return the label widget - */ - public Label createLabel(Composite parent, String text, int style) { - Label label = new Label(parent, style | orientation); - if (text != null) - label.setText(text); - adapt(label, false, false); - return label; - } - - /** - * Creates a hyperlink as a part of the form. The hyperlink will be added to - * the hyperlink group that belongs to this toolkit. - * - * @param parent - * the hyperlink parent - * @param text - * the text of the hyperlink - * @param style - * the hyperlink style - * @return the hyperlink widget - */ -// public Hyperlink createHyperlink(Composite parent, String text, int style) { -// Hyperlink hyperlink = new Hyperlink(parent, style | orientation); -// if (text != null) -// hyperlink.setText(text); -// hyperlink.addFocusListener(visibilityHandler); -// hyperlink.addKeyListener(keyboardHandler); -// hyperlinkGroup.add(hyperlink); -// return hyperlink; -// } - - /** - * Creates an image hyperlink as a part of the form. The hyperlink will be - * added to the hyperlink group that belongs to this toolkit. - * - * @param parent - * the hyperlink parent - * @param style - * the hyperlink style - * @return the image hyperlink widget - */ -// public ImageHyperlink createImageHyperlink(Composite parent, int style) { -// ImageHyperlink hyperlink = new ImageHyperlink(parent, style -// | orientation); -// hyperlink.addFocusListener(visibilityHandler); -// hyperlink.addKeyListener(keyboardHandler); -// hyperlinkGroup.add(hyperlink); -// return hyperlink; -// } - - /** - * Creates a rich text as a part of the form. - * - * @param parent - * the rich text parent - * @param trackFocus - * if true, the toolkit will monitor focus - * transfers to ensure that the hyperlink in focus is visible in - * the form. - * @return the rich text widget - * @since 1.2 - */ -// public FormText createFormText(Composite parent, boolean trackFocus) { -// FormText engine = new FormText(parent, SWT.WRAP | orientation); -// engine.marginWidth = 1; -// engine.marginHeight = 0; -// engine.setHyperlinkSettings(getHyperlinkGroup()); -// adapt(engine, trackFocus, true); -// engine.setMenu(parent.getMenu()); -// return engine; -// } - - /** - * Adapts a control to be used in a form that is associated with this - * toolkit. This involves adjusting colors and optionally adding handlers to - * ensure focus tracking and keyboard management. - * - * @param control - * a control to adapt - * @param trackFocus - * if true, form will be scrolled horizontally - * and/or vertically if needed to ensure that the control is - * visible when it gains focus. Set it to false if - * the control is not capable of gaining focus. - * @param trackKeyboard - * if true, the control that is capable of - * gaining focus will be tracked for certain keys that are - * important to the underlying form (for example, PageUp, - * PageDown, ScrollUp, ScrollDown etc.). Set it to - * false if the control is not capable of gaining - * focus or these particular key event are already used by the - * control. - */ - public void adapt(Control control, boolean trackFocus, boolean trackKeyboard) { - control.setBackground(colors.getBackground()); - control.setForeground(colors.getForeground()); -// if (control instanceof ExpandableComposite) { -// ExpandableComposite ec = (ExpandableComposite) control; -// if (ec.toggle != null) { -// if (trackFocus) -// ec.toggle.addFocusListener(visibilityHandler); -// if (trackKeyboard) -// ec.toggle.addKeyListener(keyboardHandler); -// } -// if (ec.textLabel != null) { -// if (trackFocus) -// ec.textLabel.addFocusListener(visibilityHandler); -// if (trackKeyboard) -// ec.textLabel.addKeyListener(keyboardHandler); -// } -// return; -// } - if (trackFocus) - control.addFocusListener(visibilityHandler); - if (trackKeyboard) - control.addKeyListener(keyboardHandler); - } - - /** - * Adapts a composite to be used in a form associated with this toolkit. - * - * @param composite - * the composite to adapt - */ - public void adapt(Composite composite) { - composite.setBackground(colors.getBackground()); - composite.addMouseListener(new MouseAdapter() { - public void mouseDown(MouseEvent e) { - ((Control) e.widget).setFocus(); - } - }); - if (composite.getParent() != null) - composite.setMenu(composite.getParent().getMenu()); - } - - /** - * A helper method that ensures the provided control is visible when - * ScrolledComposite is somewhere in the parent chain. If scroll bars are - * visible and the control is clipped, the client of the scrolled composite - * will be scrolled to reveal the control. - * - * @param c - * the control to reveal - */ - public static void ensureVisible(Control c) { - FormUtil.ensureVisible(c); - } - - /** - * Creates a section as a part of the form. - * - * @param parent - * the section parent - * @param sectionStyle - * the section style - * @return the section widget - */ -// public Section createSection(Composite parent, int sectionStyle) { -// Section section = new Section(parent, orientation, sectionStyle); -// section.setMenu(parent.getMenu()); -// adapt(section, true, true); -// if (section.toggle != null) { -// section.toggle.setHoverDecorationColor(colors -// .getColor(IFormColors.TB_TOGGLE_HOVER)); -// section.toggle.setDecorationColor(colors -// .getColor(IFormColors.TB_TOGGLE)); -// } -// section.setFont(boldFontHolder.getBoldFont(parent.getFont())); -// if ((sectionStyle & Section.TITLE_BAR) != 0 -// || (sectionStyle & Section.SHORT_TITLE_BAR) != 0) { -// colors.initializeSectionToolBarColors(); -// section.setTitleBarBackground(colors.getColor(IFormColors.TB_BG)); -// section.setTitleBarBorderColor(colors -// .getColor(IFormColors.TB_BORDER)); -// } -// // call setTitleBarForeground regardless as it also sets the label color -// section.setTitleBarForeground(colors -// .getColor(IFormColors.TB_TOGGLE)); -// return section; -// } - - /** - * Creates an expandable composite as a part of the form. - * - * @param parent - * the expandable composite parent - * @param expansionStyle - * the expandable composite style - * @return the expandable composite widget - */ -// public ExpandableComposite createExpandableComposite(Composite parent, -// int expansionStyle) { -// ExpandableComposite ec = new ExpandableComposite(parent, orientation, -// expansionStyle); -// ec.setMenu(parent.getMenu()); -// adapt(ec, true, true); -// ec.setFont(boldFontHolder.getBoldFont(ec.getFont())); -// return ec; -// } - - /** - * Creates a separator label as a part of the form. - * - * @param parent - * the separator parent - * @param style - * the separator style - * @return the separator label - */ - public Label createSeparator(Composite parent, int style) { - Label label = new Label(parent, SWT.SEPARATOR | style | orientation); - label.setBackground(colors.getBackground()); - label.setForeground(colors.getBorderColor()); - return label; - } - - /** - * Creates a table as a part of the form. - * - * @param parent - * the table parent - * @param style - * the table style - * @return the table widget - */ - public Table createTable(Composite parent, int style) { - Table table = new Table(parent, style | borderStyle | orientation); - adapt(table, false, false); - // hookDeleteListener(table); - return table; - } - - /** - * Creates a text as a part of the form. - * - * @param parent - * the text parent - * @param value - * the text initial value - * @return the text widget - */ - public Text createText(Composite parent, String value) { - return createText(parent, value, SWT.SINGLE); - } - - /** - * Creates a text as a part of the form. - * - * @param parent - * the text parent - * @param value - * the text initial value - * @param style - * the text style - * @return the text widget - */ - public Text createText(Composite parent, String value, int style) { - Text text = new Text(parent, borderStyle | style | orientation); - if (value != null) - text.setText(value); - text.setForeground(colors.getForeground()); - text.setBackground(colors.getBackground()); - text.addFocusListener(visibilityHandler); - return text; - } - - /** - * Creates a tree widget as a part of the form. - * - * @param parent - * the tree parent - * @param style - * the tree style - * @return the tree widget - */ - public Tree createTree(Composite parent, int style) { - Tree tree = new Tree(parent, borderStyle | style | orientation); - adapt(tree, false, false); - // hookDeleteListener(tree); - return tree; - } - - /** - * Creates a scrolled form widget in the provided parent. If you do not - * require scrolling because there is already a scrolled composite up the - * parent chain, use 'createForm' instead. - * - * @param parent - * the scrolled form parent - * @return the form that can scroll itself - * @see #createForm - */ - public ScrolledComposite createScrolledForm(Composite parent) { - ScrolledComposite form = new ScrolledComposite(parent, SWT.V_SCROLL - | SWT.H_SCROLL | orientation); - form.setExpandHorizontal(true); - form.setExpandVertical(true); - form.setBackground(colors.getBackground()); - form.setForeground(colors.getColor(IFormColors.TITLE)); - form.setFont(JFaceResources.getHeaderFont()); - return form; - } - - /** - * Creates a form widget in the provided parent. Note that this widget does - * not scroll its content, so make sure there is a scrolled composite up the - * parent chain. If you require scrolling, use 'createScrolledForm' instead. - * - * @param parent - * the form parent - * @return the form that does not scroll - * @see #createScrolledForm - */ -// public Form createForm(Composite parent) { -// Form formContent = new Form(parent, orientation); -// formContent.setBackground(colors.getBackground()); -// formContent.setForeground(colors.getColor(IFormColors.TITLE)); -// formContent.setFont(JFaceResources.getHeaderFont()); -// return formContent; -// } - - /** - * Takes advantage of the gradients and other capabilities to decorate the - * form heading using colors computed based on the current skin and - * operating system. - * - * @param form - * the form to decorate - */ - -// public void decorateFormHeading(Form form) { -// Color top = colors.getColor(IFormColors.H_GRADIENT_END); -// Color bot = colors.getColor(IFormColors.H_GRADIENT_START); -// form.setTextBackground(new Color[] { top, bot }, new int[] { 100 }, -// true); -// form.setHeadColor(IFormColors.H_BOTTOM_KEYLINE1, colors -// .getColor(IFormColors.H_BOTTOM_KEYLINE1)); -// form.setHeadColor(IFormColors.H_BOTTOM_KEYLINE2, colors -// .getColor(IFormColors.H_BOTTOM_KEYLINE2)); -// form.setHeadColor(IFormColors.H_HOVER_LIGHT, colors -// .getColor(IFormColors.H_HOVER_LIGHT)); -// form.setHeadColor(IFormColors.H_HOVER_FULL, colors -// .getColor(IFormColors.H_HOVER_FULL)); -// form.setHeadColor(IFormColors.TB_TOGGLE, colors -// .getColor(IFormColors.TB_TOGGLE)); -// form.setHeadColor(IFormColors.TB_TOGGLE_HOVER, colors -// .getColor(IFormColors.TB_TOGGLE_HOVER)); -// form.setSeparatorVisible(true); -// } - - /** - * Creates a scrolled page book widget as a part of the form. - * - * @param parent - * the page book parent - * @param style - * the text style - * @return the scrolled page book widget - */ -// public ScrolledPageBook createPageBook(Composite parent, int style) { -// ScrolledPageBook book = new ScrolledPageBook(parent, style -// | orientation); -// adapt(book, true, true); -// book.setMenu(parent.getMenu()); -// return book; -// } - - /** - * Disposes the toolkit. - */ - public void dispose() { - if (isDisposed) { - return; - } - isDisposed = true; - if (colors.isShared() == false) { - colors.dispose(); - colors = null; - } - boldFontHolder.dispose(); - } - - /** - * Returns the hyperlink group that manages hyperlinks for this toolkit. - * - * @return the hyperlink group - */ -// public HyperlinkGroup getHyperlinkGroup() { -// return hyperlinkGroup; -// } - - /** - * Sets the background color for the entire toolkit. The method delegates - * the call to the FormColors object and also updates the hyperlink group so - * that hyperlinks and other objects are in sync. - * - * @param bg - * the new background color - */ - public void setBackground(Color bg) { -// hyperlinkGroup.setBackground(bg); - colors.setBackground(bg); - } - - /** - * Refreshes the hyperlink colors by loading from JFace settings. - */ -// public void refreshHyperlinkColors() { -// hyperlinkGroup.initializeDefaultForegrounds(colors.getDisplay()); -// } - -// RAP [rh] paintBordersFor not useful as no GC to actually paint borders -// /** -// * Paints flat borders for widgets created by this toolkit within the -// * provided parent. Borders will not be painted if the global border style -// * is SWT.BORDER (i.e. if native borders are used). Call this method during -// * creation of a form composite to get the borders of its children painted. -// * Care should be taken when selection layout margins. At least one pixel -// * pargin width and height must be chosen to allow the toolkit to paint the -// * border on the parent around the widgets. -// *

-// * Borders are painted for some controls that are selected by the toolkit by -// * default. If a control needs a border but is not on its list, it is -// * possible to force border in the following way: -// * -// *

-//	 *
-//	 *
-//	 *
-//	 *             widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
-//	 *
-//	 *             or
-//	 *
-//	 *             widget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
-//	 *
-//	 *
-//	 *
-//	 * 
-// * -// * @param parent -// * the parent that owns the children for which the border needs -// * to be painted. -// */ -// public void paintBordersFor(Composite parent) { -// // if (borderStyle == SWT.BORDER) -// // return; -// if (borderPainter == null) -// borderPainter = new BorderPainter(); -// parent.addPaintListener(borderPainter); -// } - - /** - * Returns the colors used by this toolkit. - * - * @return the color object - */ - public FormColors getColors() { - return colors; - } - - /** - * Returns the border style used for various widgets created by this - * toolkit. The intent of the toolkit is to create controls with styles that - * yield a 'flat' appearance. On systems where the native borders are - * already flat, we set the style to SWT.BORDER and don't paint the borders - * ourselves. Otherwise, the style is set to SWT.NULL, and borders are - * painted by the toolkit. - * - * @return the global border style - */ - public int getBorderStyle() { - return borderStyle; - } - - /** - * Returns the margin required around the children whose border is being - * painted by the toolkit using {@link #paintBordersFor(Composite)}. Since - * the border is painted around the controls on the parent, a number of - * pixels needs to be reserved for this border. For windowing systems where - * the native border is used, this margin is 0. - * - * @return the margin in the parent when children have their border painted - */ - public int getBorderMargin() { - return getBorderStyle() == SWT.BORDER ? 0 : 2; - } - - /** - * Sets the border style to be used when creating widgets. The toolkit - * chooses the correct style based on the platform but this value can be - * changed using this method. - * - * @param style - * SWT.BORDER or SWT.NULL - * @see #getBorderStyle - */ - public void setBorderStyle(int style) { - this.borderStyle = style; - } - - /** - * A utility method that ensures that the control is visible in the scrolled - * composite. The prerequisite for this method is that the control has a - * class that extends ScrolledComposite somewhere in the parent chain. If - * the control is partially or fully clipped, the composite is scrolled to - * set by setting the origin to the control origin. - * - * @param c - * the control to make visible - * @param verticalOnly - * if true, the scrolled composite will be - * scrolled only vertically if needed. Otherwise, the scrolled - * composite origin will be set to the control origin. - */ - public static void setControlVisible(Control c, boolean verticalOnly) { - ScrolledComposite scomp = FormUtil.getScrolledComposite(c); - if (scomp == null) - return; - Point location = FormUtil.getControlLocation(scomp, c); - scomp.setOrigin(location); - } - - private void initialize() { - initializeBorderStyle(); -// hyperlinkGroup = new HyperlinkGroup(colors.getDisplay()); -// hyperlinkGroup.setBackground(colors.getBackground()); - visibilityHandler = new VisibilityHandler(); - keyboardHandler = new KeyboardHandler(); - boldFontHolder = new BoldFontHolder(); - } - -// RAP [rh] revise detection of border style: can't ask OS here - private void initializeBorderStyle() { -// String osname = System.getProperty("os.name"); //$NON-NLS-1$ -// String osversion = System.getProperty("os.version"); //$NON-NLS-1$ -// if (osname.startsWith("Windows") && "5.1".compareTo(osversion) <= 0) { //$NON-NLS-1$ //$NON-NLS-2$ -// // Skinned widgets used on newer Windows (e.g. XP (5.1), Vista -// // (6.0)) -// // Check for Windows Classic. If not used, set the style to BORDER -// RGB rgb = colors.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); -// if (rgb.red != 212 || rgb.green != 208 || rgb.blue != 200) -// borderStyle = SWT.BORDER; -// } else if (osname.startsWith("Mac")) //$NON-NLS-1$ -// borderStyle = SWT.BORDER; - - borderStyle = SWT.BORDER; - } - - /** - * Returns the orientation that all the widgets created by this toolkit will - * inherit, if set. Can be SWT.NULL, - * SWT.LEFT_TO_RIGHT and SWT.RIGHT_TO_LEFT. - * - * @return orientation style for this toolkit, or SWT.NULL if - * not set. The default orientation is inherited from the Window - * default orientation. - * @see org.eclipse.jface.window.Window#getDefaultOrientation() - */ - - public int getOrientation() { - return orientation; - } - - /** - * Sets the orientation that all the widgets created by this toolkit will - * inherit. Can be SWT.NULL, SWT.LEFT_TO_RIGHT - * and SWT.RIGHT_TO_LEFT. - * - * @param orientation - * style for this toolkit. - */ - - public void setOrientation(int orientation) { - this.orientation = orientation; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormUtil.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormUtil.java deleted file mode 100644 index 76e3f1104..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/FormUtil.java +++ /dev/null @@ -1,522 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.events.MouseEvent; -//import org.eclipse.swt.graphics.Device; -import org.eclipse.swt.graphics.FontMetrics; -import org.eclipse.swt.graphics.GC; -//import org.eclipse.swt.graphics.Image; -//import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Layout; -//import org.eclipse.swt.widgets.ScrollBar; -import org.eclipse.swt.widgets.Text; -//import org.eclipse.ui.forms.widgets.ColumnLayout; -//import org.eclipse.ui.forms.widgets.Form; -//import org.eclipse.ui.forms.widgets.FormText; -//import org.eclipse.ui.forms.widgets.FormToolkit; -//import org.eclipse.ui.forms.widgets.ILayoutExtension; -// -//import com.ibm.icu.text.BreakIterator; - -public class FormUtil { - public static final String PLUGIN_ID = "org.eclipse.ui.forms"; //$NON-NLS-1$ - - static final int H_SCROLL_INCREMENT = 5; - - static final int V_SCROLL_INCREMENT = 64; - - public static final String DEBUG = PLUGIN_ID + "/debug"; //$NON-NLS-1$ - - public static final String DEBUG_TEXT = DEBUG + "/text"; //$NON-NLS-1$ - public static final String DEBUG_TEXTSIZE = DEBUG + "/textsize"; //$NON-NLS-1$ - - public static final String DEBUG_FOCUS = DEBUG + "/focus"; //$NON-NLS-1$ - - public static final String FOCUS_SCROLLING = "focusScrolling"; //$NON-NLS-1$ - - public static final String IGNORE_BODY = "__ignore_body__"; //$NON-NLS-1$ - - public static Text createText(Composite parent, String label, - FormToolkit factory) { - return createText(parent, label, factory, 1); - } - - public static Text createText(Composite parent, String label, - FormToolkit factory, int span) { - factory.createLabel(parent, label); - Text text = factory.createText(parent, ""); //$NON-NLS-1$ - int hfill = span == 1 ? GridData.FILL_HORIZONTAL - : GridData.HORIZONTAL_ALIGN_FILL; - GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER); - gd.horizontalSpan = span; - text.setLayoutData(gd); - return text; - } - - public static Text createText(Composite parent, String label, - FormToolkit factory, int span, int style) { - Label l = factory.createLabel(parent, label); - if ((style & SWT.MULTI) != 0) { - GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); - l.setLayoutData(gd); - } - Text text = factory.createText(parent, "", style); //$NON-NLS-1$ - int hfill = span == 1 ? GridData.FILL_HORIZONTAL - : GridData.HORIZONTAL_ALIGN_FILL; - GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER); - gd.horizontalSpan = span; - text.setLayoutData(gd); - return text; - } - - public static Text createText(Composite parent, FormToolkit factory, - int span) { - Text text = factory.createText(parent, ""); //$NON-NLS-1$ - int hfill = span == 1 ? GridData.FILL_HORIZONTAL - : GridData.HORIZONTAL_ALIGN_FILL; - GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER); - gd.horizontalSpan = span; - text.setLayoutData(gd); - return text; - } - - public static int computeMinimumWidth(GC gc, String text) { -// BreakIterator wb = BreakIterator.getWordInstance(); -// wb.setText(text); -// int last = 0; -// -// int width = 0; -// -// for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) { -// String word = text.substring(last, loc); -// Point extent = gc.textExtent(word); -// width = Math.max(width, extent.x); -// last = loc; -// } -// String lastWord = text.substring(last); -// Point extent = gc.textExtent(lastWord); -// width = Math.max(width, extent.x); -// return width; - return 0; - } - - public static Point computeWrapSize(GC gc, String text, int wHint) { -// BreakIterator wb = BreakIterator.getWordInstance(); -// wb.setText(text); - FontMetrics fm = gc.getFontMetrics(); - int lineHeight = fm.getHeight(); - - int saved = 0; - int last = 0; - int height = lineHeight; - int maxWidth = 0; -// for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) { -// String word = text.substring(saved, loc); -// Point extent = gc.textExtent(word); -// if (extent.x > wHint) { -// // overflow -// saved = last; -// height += extent.y; -// // switch to current word so maxWidth will accommodate very long single words -// word = text.substring(last, loc); -// extent = gc.textExtent(word); -// } -// maxWidth = Math.max(maxWidth, extent.x); -// last = loc; -// } - /* - * Correct the height attribute in case it was calculated wrong due to wHint being less than maxWidth. - * The recursive call proved to be the only thing that worked in all cases. Some attempts can be made - * to estimate the height, but the algorithm needs to be run again to be sure. - */ - if (maxWidth > wHint) - return computeWrapSize(gc, text, maxWidth); - return new Point(maxWidth, height); - } - -// RAP [rh] paintWrapText unnecessary -// public static void paintWrapText(GC gc, String text, Rectangle bounds) { -// paintWrapText(gc, text, bounds, false); -// } - -// RAP [rh] paintWrapText unnecessary -// public static void paintWrapText(GC gc, String text, Rectangle bounds, -// boolean underline) { -// BreakIterator wb = BreakIterator.getWordInstance(); -// wb.setText(text); -// FontMetrics fm = gc.getFontMetrics(); -// int lineHeight = fm.getHeight(); -// int descent = fm.getDescent(); -// -// int saved = 0; -// int last = 0; -// int y = bounds.y; -// int width = bounds.width; -// -// for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) { -// String line = text.substring(saved, loc); -// Point extent = gc.textExtent(line); -// -// if (extent.x > width) { -// // overflow -// String prevLine = text.substring(saved, last); -// gc.drawText(prevLine, bounds.x, y, true); -// if (underline) { -// Point prevExtent = gc.textExtent(prevLine); -// int lineY = y + lineHeight - descent + 1; -// gc -// .drawLine(bounds.x, lineY, bounds.x + prevExtent.x, -// lineY); -// } -// -// saved = last; -// y += lineHeight; -// } -// last = loc; -// } -// // paint the last line -// String lastLine = text.substring(saved, last); -// gc.drawText(lastLine, bounds.x, y, true); -// if (underline) { -// int lineY = y + lineHeight - descent + 1; -// Point lastExtent = gc.textExtent(lastLine); -// gc.drawLine(bounds.x, lineY, bounds.x + lastExtent.x, lineY); -// } -// } - - public static ScrolledComposite getScrolledComposite(Control c) { - Composite parent = c.getParent(); - - while (parent != null) { - if (parent instanceof ScrolledComposite) { - return (ScrolledComposite) parent; - } - parent = parent.getParent(); - } - return null; - } - - public static void ensureVisible(Control c) { - ScrolledComposite scomp = getScrolledComposite(c); - if (scomp != null) { - Object data = scomp.getData(FOCUS_SCROLLING); - if (data == null || !data.equals(Boolean.FALSE)) - FormUtil.ensureVisible(scomp, c); - } - } - - public static void ensureVisible(ScrolledComposite scomp, Control control) { - // if the control is a FormText we do not need to scroll since it will - // ensure visibility of its segments as necessary -// if (control instanceof FormText) -// return; - Point controlSize = control.getSize(); - Point controlOrigin = getControlLocation(scomp, control); - ensureVisible(scomp, controlOrigin, controlSize); - } - - public static void ensureVisible(ScrolledComposite scomp, - Point controlOrigin, Point controlSize) { - Rectangle area = scomp.getClientArea(); - Point scompOrigin = scomp.getOrigin(); - - int x = scompOrigin.x; - int y = scompOrigin.y; - - // horizontal right, but only if the control is smaller - // than the client area - if (controlSize.x < area.width - && (controlOrigin.x + controlSize.x > scompOrigin.x - + area.width)) { - x = controlOrigin.x + controlSize.x - area.width; - } - // horizontal left - make sure the left edge of - // the control is showing - if (controlOrigin.x < x) { - if (controlSize.x < area.width) - x = controlOrigin.x + controlSize.x - area.width; - else - x = controlOrigin.x; - } - // vertical bottom - if (controlSize.y < area.height - && (controlOrigin.y + controlSize.y > scompOrigin.y - + area.height)) { - y = controlOrigin.y + controlSize.y - area.height; - } - // vertical top - make sure the top of - // the control is showing - if (controlOrigin.y < y) { - if (controlSize.y < area.height) - y = controlOrigin.y + controlSize.y - area.height; - else - y = controlOrigin.y; - } - - if (scompOrigin.x != x || scompOrigin.y != y) { - // scroll to reveal - scomp.setOrigin(x, y); - } - } - - public static void ensureVisible(ScrolledComposite scomp, Control control, - MouseEvent e) { - Point controlOrigin = getControlLocation(scomp, control); - int rX = controlOrigin.x + e.x; - int rY = controlOrigin.y + e.y; - Rectangle area = scomp.getClientArea(); - Point scompOrigin = scomp.getOrigin(); - - int x = scompOrigin.x; - int y = scompOrigin.y; - // System.out.println("Ensure: area="+area+", origin="+scompOrigin+", - // cloc="+controlOrigin+", csize="+controlSize+", x="+x+", y="+y); - - // horizontal right - if (rX > scompOrigin.x + area.width) { - x = rX - area.width; - } - // horizontal left - else if (rX < x) { - x = rX; - } - // vertical bottom - if (rY > scompOrigin.y + area.height) { - y = rY - area.height; - } - // vertical top - else if (rY < y) { - y = rY; - } - - if (scompOrigin.x != x || scompOrigin.y != y) { - // scroll to reveal - scomp.setOrigin(x, y); - } - } - - public static Point getControlLocation(ScrolledComposite scomp, - Control control) { - int x = 0; - int y = 0; - Control content = scomp.getContent(); - Control currentControl = control; - for (;;) { - if (currentControl == content) - break; - Point location = currentControl.getLocation(); - // if (location.x > 0) - // x += location.x; - // if (location.y > 0) - // y += location.y; - x += location.x; - y += location.y; - currentControl = currentControl.getParent(); - } - return new Point(x, y); - } - - static void scrollVertical(ScrolledComposite scomp, boolean up) { - scroll(scomp, 0, up ? -V_SCROLL_INCREMENT : V_SCROLL_INCREMENT); - } - - static void scrollHorizontal(ScrolledComposite scomp, boolean left) { - scroll(scomp, left ? -H_SCROLL_INCREMENT : H_SCROLL_INCREMENT, 0); - } - - static void scrollPage(ScrolledComposite scomp, boolean up) { - Rectangle clientArea = scomp.getClientArea(); - int increment = up ? -clientArea.height : clientArea.height; - scroll(scomp, 0, increment); - } - - static void scroll(ScrolledComposite scomp, int xoffset, int yoffset) { - Point origin = scomp.getOrigin(); - Point contentSize = scomp.getContent().getSize(); - int xorigin = origin.x + xoffset; - int yorigin = origin.y + yoffset; - xorigin = Math.max(xorigin, 0); - xorigin = Math.min(xorigin, contentSize.x - 1); - yorigin = Math.max(yorigin, 0); - yorigin = Math.min(yorigin, contentSize.y - 1); - scomp.setOrigin(xorigin, yorigin); - } - -// RAP [rh] FormUtil#updatePageIncrement: empty implementation - public static void updatePageIncrement(ScrolledComposite scomp) { -// ScrollBar vbar = scomp.getVerticalBar(); -// if (vbar != null) { -// Rectangle clientArea = scomp.getClientArea(); -// int increment = clientArea.height - 5; -// vbar.setPageIncrement(increment); -// } -// ScrollBar hbar = scomp.getHorizontalBar(); -// if (hbar != null) { -// Rectangle clientArea = scomp.getClientArea(); -// int increment = clientArea.width - 5; -// hbar.setPageIncrement(increment); -// } - } - - public static void processKey(int keyCode, Control c) { - if (c.isDisposed()) { - return; - } - ScrolledComposite scomp = FormUtil.getScrolledComposite(c); - if (scomp != null) { - if (c instanceof Combo) - return; - switch (keyCode) { - case SWT.ARROW_DOWN: - if (scomp.getData("novarrows") == null) //$NON-NLS-1$ - FormUtil.scrollVertical(scomp, false); - break; - case SWT.ARROW_UP: - if (scomp.getData("novarrows") == null) //$NON-NLS-1$ - FormUtil.scrollVertical(scomp, true); - break; - case SWT.ARROW_LEFT: - FormUtil.scrollHorizontal(scomp, true); - break; - case SWT.ARROW_RIGHT: - FormUtil.scrollHorizontal(scomp, false); - break; - case SWT.PAGE_UP: - FormUtil.scrollPage(scomp, true); - break; - case SWT.PAGE_DOWN: - FormUtil.scrollPage(scomp, false); - break; - } - } - } - - public static boolean isWrapControl(Control c) { - if ((c.getStyle() & SWT.WRAP) != 0) - return true; - if (c instanceof Composite) { - return false; -// return ((Composite) c).getLayout() instanceof ILayoutExtension; - } - return false; - } - - public static int getWidthHint(int wHint, Control c) { - boolean wrap = isWrapControl(c); - return wrap ? wHint : SWT.DEFAULT; - } - - public static int getHeightHint(int hHint, Control c) { - if (c instanceof Composite) { - Layout layout = ((Composite) c).getLayout(); -// if (layout instanceof ColumnLayout) -// return hHint; - } - return SWT.DEFAULT; - } - - public static int computeMinimumWidth(Control c, boolean changed) { - if (c instanceof Composite) { - Layout layout = ((Composite) c).getLayout(); -// if (layout instanceof ILayoutExtension) -// return ((ILayoutExtension) layout).computeMinimumWidth( -// (Composite) c, changed); - } - return c.computeSize(FormUtil.getWidthHint(5, c), SWT.DEFAULT, changed).x; - } - - public static int computeMaximumWidth(Control c, boolean changed) { - if (c instanceof Composite) { - Layout layout = ((Composite) c).getLayout(); -// if (layout instanceof ILayoutExtension) -// return ((ILayoutExtension) layout).computeMaximumWidth( -// (Composite) c, changed); - } - return c.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed).x; - } - -// public static Form getForm(Control c) { -// Composite parent = c.getParent(); -// while (parent != null) { -// if (parent instanceof Form) { -// return (Form) parent; -// } -// parent = parent.getParent(); -// } -// return null; -// } - -// RAP [rh] FormUtil#createAlphaMashImage unnecessary -// public static Image createAlphaMashImage(Device device, Image srcImage) { -// Rectangle bounds = srcImage.getBounds(); -// int alpha = 0; -// int calpha = 0; -// ImageData data = srcImage.getImageData(); -// // Create a new image with alpha values alternating -// // between fully transparent (0) and fully opaque (255). -// // This image will show the background through the -// // transparent pixels. -// for (int i = 0; i < bounds.height; i++) { -// // scan line -// alpha = calpha; -// for (int j = 0; j < bounds.width; j++) { -// // column -// data.setAlpha(j, i, alpha); -// alpha = alpha == 255 ? 0 : 255; -// } -// calpha = calpha == 255 ? 0 : 255; -// } -// return new Image(device, data); -// } - - public static boolean mnemonicMatch(String text, char key) { - char mnemonic = findMnemonic(text); - if (mnemonic == '\0') - return false; - return Character.toUpperCase(key) == Character.toUpperCase(mnemonic); - } - - private static char findMnemonic(String string) { - int index = 0; - int length = string.length(); - do { - while (index < length && string.charAt(index) != '&') - index++; - if (++index >= length) - return '\0'; - if (string.charAt(index) != '&') - return string.charAt(index); - index++; - } while (index < length); - return '\0'; - } - - public static void setFocusScrollingEnabled(Control c, boolean enabled) { - ScrolledComposite scomp = null; - - if (c instanceof ScrolledComposite) - scomp = (ScrolledComposite)c; - else - scomp = getScrolledComposite(c); - if (scomp!=null) - scomp.setData(FormUtil.FOCUS_SCROLLING, enabled?null:Boolean.FALSE); - } - - // RAP [rh] FormUtil#setAntialias unnecessary -// public static void setAntialias(GC gc, int style) { -// if (!gc.getAdvanced()) { -// gc.setAdvanced(true); -// if (!gc.getAdvanced()) -// return; -// } -// gc.setAntialias(style); -// } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormColors.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormColors.java deleted file mode 100644 index cf0e5d35e..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormColors.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -/** - * A place to hold all the color constants used in the forms package. - * - * @since 1.0 - */ - -public interface IFormColors { - /** - * A prefix for all the keys. - */ - String PREFIX = "org.eclipse.ui.forms."; //$NON-NLS-1$ - /** - * Key for the form title foreground color. - */ - String TITLE = PREFIX + "TITLE"; //$NON-NLS-1$ - - /** - * A prefix for the header color constants. - */ - String H_PREFIX = PREFIX + "H_"; //$NON-NLS-1$ - /* - * A prefix for the section title bar color constants. - */ - String TB_PREFIX = PREFIX + "TB_"; //$NON-NLS-1$ - /** - * Key for the form header background gradient ending color. - */ - String H_GRADIENT_END = H_PREFIX + "GRADIENT_END"; //$NON-NLS-1$ - - /** - * Key for the form header background gradient starting color. - * - */ - String H_GRADIENT_START = H_PREFIX + "GRADIENT_START"; //$NON-NLS-1$ - /** - * Key for the form header bottom keyline 1 color. - * - */ - String H_BOTTOM_KEYLINE1 = H_PREFIX + "BOTTOM_KEYLINE1"; //$NON-NLS-1$ - /** - * Key for the form header bottom keyline 2 color. - * - */ - String H_BOTTOM_KEYLINE2 = H_PREFIX + "BOTTOM_KEYLINE2"; //$NON-NLS-1$ - /** - * Key for the form header light hover color. - * - */ - String H_HOVER_LIGHT = H_PREFIX + "H_HOVER_LIGHT"; //$NON-NLS-1$ - /** - * Key for the form header full hover color. - * - */ - String H_HOVER_FULL = H_PREFIX + "H_HOVER_FULL"; //$NON-NLS-1$ - - /** - * Key for the tree/table border color. - */ - String BORDER = PREFIX + "BORDER"; //$NON-NLS-1$ - - /** - * Key for the section separator color. - */ - String SEPARATOR = PREFIX + "SEPARATOR"; //$NON-NLS-1$ - - /** - * Key for the section title bar background. - */ - String TB_BG = TB_PREFIX + "BG"; //$NON-NLS-1$ - - /** - * Key for the section title bar foreground. - */ - String TB_FG = TB_PREFIX + "FG"; //$NON-NLS-1$ - - /** - * Key for the section title bar gradient. - * @deprecated Since 3.3, this color is not used any more. The - * tool bar gradient is created starting from {@link #TB_BG} to - * the section background color. - */ - String TB_GBG = TB_BG; - - /** - * Key for the section title bar border. - */ - String TB_BORDER = TB_PREFIX + "BORDER"; //$NON-NLS-1$ - - /** - * Key for the section toggle color. Since 3.1, this color is used for all - * section styles. - */ - String TB_TOGGLE = TB_PREFIX + "TOGGLE"; //$NON-NLS-1$ - - /** - * Key for the section toggle hover color. - * - */ - String TB_TOGGLE_HOVER = TB_PREFIX + "TOGGLE_HOVER"; //$NON-NLS-1$ -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormPart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormPart.java deleted file mode 100644 index 954cc0372..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IFormPart.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -/** - * Classes that implement this interface can be added to the managed form and - * take part in the form life cycle. The part is initialized with the form and - * will be asked to accept focus. The part can receive form input and can elect - * to do something according to it (for example, select an object that matches - * the input). - *

- * The form part has two 'out of sync' states in respect to the model(s) that - * feed the form: dirty and stale. When a part is dirty, it - * means that the user interacted with it and now its widgets contain state that - * is newer than the model. In order to sync up with the model, 'commit' needs - * to be called. In contrast, the model can change 'under' the form (as a result - * of some actions outside the form), resulting in data in the model being - * 'newer' than the content presented in the form. A 'stale' form part is - * brought in sync with the model by calling 'refresh'. The part is responsible - * for notifying the form when one of these states change in the part. The form - * reserves the right to handle this notification in the most appropriate way - * for the situation (for example, if the form is in a page of the multi-page - * editor, it may do nothing for stale parts if the page is currently not - * showing). - *

- * When the form is disposed, each registered part is disposed as well. Parts - * are responsible for releasing any system resources they created and for - * removing themselves as listeners from all event providers. - * - * @see IManagedForm - * @since 1.0 - * - */ -public interface IFormPart { - /** - * Initializes the part. - * - * @param form - * the managed form that manages the part - */ - void initialize(IManagedForm form); - - /** - * Disposes the part allowing it to release allocated resources. - */ - void dispose(); - - /** - * Returns true if the part has been modified with respect to the data - * loaded from the model. - * - * @return true if the part has been modified with respect to the data - * loaded from the model - */ - boolean isDirty(); - - /** - * If part is displaying information loaded from a model, this method - * instructs it to commit the new (modified) data back into the model. - * - * @param onSave - * indicates if commit is called during 'save' operation or for - * some other reason (for example, if form is contained in a - * wizard or a multi-page editor and the user is about to leave - * the page). - */ - void commit(boolean onSave); - - /** - * Notifies the part that an object has been set as overall form's input. - * The part can elect to react by revealing or selecting the object, or do - * nothing if not applicable. - * - * @return true if the part has selected and revealed the - * input object, false otherwise. - */ - boolean setFormInput(Object input); - - /** - * Instructs form part to transfer focus to the widget that should has focus - * in that part. The method can do nothing (if it has no widgets capable of - * accepting focus). - */ - void setFocus(); - - /** - * Tests whether the form part is stale and needs refreshing. Parts can - * receive notification from models that will make their content stale, but - * may need to delay refreshing to improve performance (for example, there - * is no need to immediately refresh a part on a form that is current on a - * hidden page). - *

- * It is important to differentiate 'stale' and 'dirty' states. Part is - * 'dirty' if user interacted with its editable widgets and changed the - * values. In contrast, part is 'stale' when the data it presents in the - * widgets has been changed in the model without direct user interaction. - * - * @return true if the part needs refreshing, - * false otherwise. - */ - boolean isStale(); - - /** - * Refreshes the part completely from the information freshly obtained from - * the model. The method will not be called if the part is not stale. - * Otherwise, the part is responsible for clearing the 'stale' flag after - * refreshing itself. - */ - void refresh(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IManagedForm.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IManagedForm.java deleted file mode 100644 index 490d3a303..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IManagedForm.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.custom.ScrolledComposite; -//import org.eclipse.ui.forms.widgets.FormToolkit; -//import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Managed form wraps a form widget and adds life cycle methods for form parts. - * A form part is a portion of the form that participates in form life cycle - * events. - *

- * There is no 1/1 mapping between widgets and form parts. A widget like Section - * can be a part by itself, but a number of widgets can gather around one form - * part. - *

- * This interface should not be extended or implemented. New form instances - * should be created using ManagedForm. - * - * @see ManagedForm - * @since 1.0 - * @noimplement This interface is not intended to be implemented by clients. - * @noextend This interface is not intended to be extended by clients. - */ -public interface IManagedForm { - /** - * Initializes the form by looping through the managed parts and - * initializing them. Has no effect if already called once. - */ - public void initialize(); - - /** - * Returns the toolkit used by this form. - * - * @return the toolkit - */ - public FormToolkit getToolkit(); - - /** - * Returns the form widget managed by this form. - * - * @return the form widget - */ - public ScrolledComposite getForm(); - - /** - * Reflows the form as a result of the layout change. - * - * @param changed - * if true, discard cached layout information - */ - public void reflow(boolean changed); - - /** - * A part can use this method to notify other parts that implement - * IPartSelectionListener about selection changes. - * - * @param part - * the part that broadcasts the selection - * @param selection - * the selection in the part - */ - public void fireSelectionChanged(IFormPart part, ISelection selection); - - /** - * Returns all the parts currently managed by this form. - * - * @return the managed parts - */ - IFormPart[] getParts(); - - /** - * Adds the new part to the form. - * - * @param part - * the part to add - */ - void addPart(IFormPart part); - - /** - * Removes the part from the form. - * - * @param part - * the part to remove - */ - void removePart(IFormPart part); - - /** - * Sets the input of this page to the provided object. - * - * @param input - * the new page input - * @return true if the form contains this object, - * false otherwise. - */ - boolean setInput(Object input); - - /** - * Returns the current page input. - * - * @return page input object or null if not applicable. - */ - Object getInput(); - - /** - * Tests if form is dirty. A managed form is dirty if at least one managed - * part is dirty. - * - * @return true if at least one managed part is dirty, - * false otherwise. - */ - boolean isDirty(); - - /** - * Notifies the form that the dirty state of one of its parts has changed. - * The global dirty state of the form can be obtained by calling 'isDirty'. - * - * @see #isDirty - */ - void dirtyStateChanged(); - - /** - * Commits the dirty form. All pending changes in the widgets are flushed - * into the model. - * - * @param onSave - */ - void commit(boolean onSave); - - /** - * Tests if form is stale. A managed form is stale if at least one managed - * part is stale. This can happen when the underlying model changes, - * resulting in the presentation of the part being out of sync with the - * model and needing refreshing. - * - * @return true if the form is stale, false - * otherwise. - */ - boolean isStale(); - - /** - * Notifies the form that the stale state of one of its parts has changed. - * The global stale state of the form can be obtained by calling 'isStale'. - */ - void staleStateChanged(); - - /** - * Refreshes the form by refreshing every part that is stale. - */ - void refresh(); - - /** - * Sets the container that owns this form. Depending on the context, the - * container may be wizard, editor page, editor etc. - * - * @param container - * the container of this form - */ - void setContainer(Object container); - - /** - * Returns the container of this form. - * - * @return the form container - */ - Object getContainer(); - - /** - * Returns the message manager that will keep track of messages in this - * form. - * - * @return the message manager instance - */ -// IMessageManager getMessageManager(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IPartSelectionListener.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IPartSelectionListener.java deleted file mode 100644 index 0f557d41f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/IPartSelectionListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import org.eclipse.jface.viewers.ISelection; - -/** - * Form parts can implement this interface if they want to be - * notified when another part on the same form changes selection - * state. - * - * @see IFormPart - * @since 1.0 - */ -public interface IPartSelectionListener { - /** - * Called when the provided part has changed selection state. - * - * @param part - * the selection source - * @param selection - * the new selection - */ - public void selectionChanged(IFormPart part, ISelection selection); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/ManagedForm.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/ManagedForm.java deleted file mode 100644 index 4140465a1..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/ManagedForm.java +++ /dev/null @@ -1,323 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms; - -import java.util.Vector; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.widgets.Composite; -//import org.eclipse.ui.forms.widgets.FormToolkit; -//import org.eclipse.ui.forms.widgets.ScrolledForm; - -/** - * Managed form wraps a form widget and adds life cycle methods for form parts. - * A form part is a portion of the form that participates in form life cycle - * events. - *

- * There is requirement for 1/1 mapping between widgets and form parts. A widget - * like Section can be a part by itself, but a number of widgets can join around - * one form part. - *

- * Note to developers: this class is left public to allow its use beyond the - * original intention (inside a multi-page editor's page). You should limit the - * use of this class to make new instances inside a form container (wizard page, - * dialog etc.). Clients that need access to the class should not do it - * directly. Instead, they should do it through IManagedForm interface as much - * as possible. - * - * @since 1.0 - */ -public class ManagedForm implements IManagedForm { - private Object input; - - private ScrolledComposite form; - - private FormToolkit toolkit; - - private Object container; - - private boolean ownsToolkit; - - private boolean initialized; - - private Vector parts = new Vector(); - - /** - * Creates a managed form in the provided parent. Form toolkit and widget - * will be created and owned by this object. - * - * @param parent - * the parent widget - */ - public ManagedForm(Composite parent) { - toolkit = new FormToolkit(parent.getDisplay()); - ownsToolkit = true; - form = toolkit.createScrolledForm(parent); - - } - - /** - * Creates a managed form that will use the provided toolkit and - * - * @param toolkit - * @param form - */ - public ManagedForm(FormToolkit toolkit, ScrolledComposite form) { - this.form = form; - this.toolkit = toolkit; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#addPart(org.eclipse.ui.forms.IFormPart) - */ - public void addPart(IFormPart part) { - parts.add(part); - part.initialize(this); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#removePart(org.eclipse.ui.forms.IFormPart) - */ - public void removePart(IFormPart part) { - parts.remove(part); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#getParts() - */ - public IFormPart[] getParts() { - return (IFormPart[]) parts.toArray(new IFormPart[parts.size()]); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#getToolkit() - */ - public FormToolkit getToolkit() { - return toolkit; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#getForm() - */ - public ScrolledComposite getForm() { - return form; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#reflow(boolean) - */ - public void reflow(boolean changed) { -// form.reflow(changed); - } - - /** - * A part can use this method to notify other parts that implement - * IPartSelectionListener about selection changes. - * - * @param part - * the part that broadcasts the selection - * @param selection - * the selection in the part - * @see IPartSelectionListener - */ - public void fireSelectionChanged(IFormPart part, ISelection selection) { - for (int i = 0; i < parts.size(); i++) { - IFormPart cpart = (IFormPart) parts.get(i); - if (part.equals(cpart)) - continue; -// if (cpart instanceof IPartSelectionListener) { -// ((IPartSelectionListener) cpart).selectionChanged(part, -// selection); -// } - } - } - - /** - * Initializes the form by looping through the managed parts and - * initializing them. Has no effect if already called once. - */ - public void initialize() { - if (initialized) - return; - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - part.initialize(this); - } - initialized = true; - } - - /** - * Disposes all the parts in this form. - */ - public void dispose() { - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - part.dispose(); - } - if (ownsToolkit) { - toolkit.dispose(); - } - } - - /** - * Refreshes the form by refreshes all the stale parts. Since 3.1, this - * method is performed on a UI thread when called from another thread so it - * is not needed to wrap the call in Display.syncExec or - * asyncExec. - */ - public void refresh() { - Thread t = Thread.currentThread(); - Thread dt = toolkit.getColors().getDisplay().getThread(); - if (t.equals(dt)) - doRefresh(); - else { - toolkit.getColors().getDisplay().asyncExec(new Runnable() { - public void run() { - doRefresh(); - } - }); - } - } - - private void doRefresh() { - int nrefreshed = 0; - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - if (part.isStale()) { - part.refresh(); - nrefreshed++; - } - } -// if (nrefreshed > 0) -// form.reflow(true); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#commit(boolean) - */ - public void commit(boolean onSave) { - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - if (part.isDirty()) - part.commit(onSave); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#setInput(java.lang.Object) - */ - public boolean setInput(Object input) { - boolean pageResult = false; - - this.input = input; - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - boolean result = part.setFormInput(input); - if (result) - pageResult = true; - } - return pageResult; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#getInput() - */ - public Object getInput() { - return input; - } - - /** - * Transfers the focus to the first form part. - */ - public void setFocus() { - if (parts.size() > 0) { - IFormPart part = (IFormPart) parts.get(0); - part.setFocus(); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#isDirty() - */ - public boolean isDirty() { - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - if (part.isDirty()) - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#isStale() - */ - public boolean isStale() { - for (int i = 0; i < parts.size(); i++) { - IFormPart part = (IFormPart) parts.get(i); - if (part.isStale()) - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#dirtyStateChanged() - */ - public void dirtyStateChanged() { - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#staleStateChanged() - */ - public void staleStateChanged() { - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#getContainer() - */ - public Object getContainer() { - return container; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.forms.IManagedForm#setContainer(java.lang.Object) - */ - public void setContainer(Object container) { - this.container = container; - } - - /* (non-Javadoc) - * @see org.eclipse.ui.forms.IManagedForm#getMessageManager() - */ -// public IMessageManager getMessageManager() { -// return form.getMessageManager(); -// } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormEditor.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormEditor.java deleted file mode 100644 index 484dae842..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormEditor.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms.editor; - -import org.argeo.cms.ui.eclipse.forms.FormToolkit; -import org.eclipse.jface.dialogs.IPageChangeProvider; - -/** - * This class forms a base of multi-page form editors that typically use one or - * more pages with forms and one page for raw source of the editor input. - *

- * Pages are added 'lazily' i.e. adding a page reserves a tab for it but does - * not cause the page control to be created. Page control is created when an - * attempt is made to select the page in question. This allows editors with - * several tabs and complex pages to open quickly. - *

- * Subclasses should extend this class and implement addPages - * method. One of the two addPage methods should be called to - * contribute pages to the editor. One adds complete (standalone) editors as - * nested tabs. These editors will be created right away and will be hooked so - * that key bindings, selection service etc. is compatible with the one for the - * standalone case. The other method adds classes that implement - * IFormPage interface. These pages will be created lazily and - * they will share the common key binding and selection service. Since 3.1, - * FormEditor is a page change provider. It allows listeners to attach to it and - * get notified when pages are changed. This new API in JFace allows dynamic - * help to update on page changes. - * - * @since 1.0 - */ -// RAP [if] As RAP is still using workbench 3.4, the implementation of -// IPageChangeProvider is missing from MultiPageEditorPart. Remove this code -// with the adoption of workbench > 3.5 -//public abstract class FormEditor extends MultiPageEditorPart { -public abstract class FormEditor implements - IPageChangeProvider { - private FormToolkit formToolkit; - - -public FormToolkit getToolkit() { - return formToolkit; - } - -public void editorDirtyStateChanged() { - -} - -public FormPage getActivePageInstance() { - return null; -} - - // RAP [if] As RAP is still using workbench 3.4, the implementation of -// IPageChangeProvider is missing from MultiPageEditorPart. Remove this code -// with the adoption of workbench > 3.5 -// private ListenerList pageListeners = new ListenerList(); -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.jface.dialogs.IPageChangeProvider#addPageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) -// */ -// public void addPageChangedListener(IPageChangedListener listener) { -// pageListeners.add(listener); -// } -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.jface.dialogs.IPageChangeProvider#removePageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) -// */ -// public void removePageChangedListener(IPageChangedListener listener) { -// pageListeners.remove(listener); -// } -// -// private void firePageChanged(final PageChangedEvent event) { -// Object[] listeners = pageListeners.getListeners(); -// for (int i = 0; i < listeners.length; ++i) { -// final IPageChangedListener l = (IPageChangedListener) listeners[i]; -// SafeRunnable.run(new SafeRunnable() { -// public void run() { -// l.pageChanged(event); -// } -// }); -// } -// } -// RAPEND [if] -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormPage.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormPage.java deleted file mode 100644 index a788412db..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/FormPage.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms.editor; -import org.argeo.cms.ui.eclipse.forms.IManagedForm; -import org.argeo.cms.ui.eclipse.forms.ManagedForm; -import org.eclipse.swt.custom.BusyIndicator; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -/** - * A base class that all pages that should be added to FormEditor must subclass. - * Form page has an instance of PageForm that extends managed form. Subclasses - * should override method 'createFormContent(ManagedForm)' to fill the form with - * content. Note that page itself can be loaded lazily (on first open). - * Consequently, the call to create the form content can come after the editor - * has been opened for a while (in fact, it is possible to open and close the - * editor and never create the form because no attempt has been made to show the - * page). - * - * @since 1.0 - */ -public class FormPage implements IFormPage { - private FormEditor editor; - private PageForm mform; - private int index; - private String id; - - private String partName; - - - - public void setPartName(String partName) { - this.partName = partName; - } - private static class PageForm extends ManagedForm { - public PageForm(FormPage page, ScrolledComposite form) { - super(page.getEditor().getToolkit(), form); - setContainer(page); - } - - public FormPage getPage() { - return (FormPage)getContainer(); - } - public void dirtyStateChanged() { - getPage().getEditor().editorDirtyStateChanged(); - } - public void staleStateChanged() { - if (getPage().isActive()) - refresh(); - } - } - /** - * A constructor that creates the page and initializes it with the editor. - * - * @param editor - * the parent editor - * @param id - * the unique identifier - * @param title - * the page title - */ - public FormPage(FormEditor editor, String id, String title) { - this(id, title); - initialize(editor); - } - /** - * The constructor. The parent editor need to be passed in the - * initialize method if this constructor is used. - * - * @param id - * a unique page identifier - * @param title - * a user-friendly page title - */ - public FormPage(String id, String title) { - this.id = id; - setPartName(title); - } - /** - * Initializes the form page. - * - * @see IEditorPart#init - */ -// public void init(IEditorSite site, IEditorInput input) { -// setSite(site); -// setInput(input); -// } - /** - * Primes the form page with the parent editor instance. - * - * @param editor - * the parent editor - */ - public void initialize(FormEditor editor) { - this.editor = editor; - } - /** - * Returns the parent editor. - * - * @return parent editor instance - */ - public FormEditor getEditor() { - return editor; - } - /** - * Returns the managed form owned by this page. - * - * @return the managed form - */ - public IManagedForm getManagedForm() { - return mform; - } - /** - * Implements the required method by refreshing the form when set active. - * Subclasses must call super when overriding this method. - */ - public void setActive(boolean active) { - if (active) { - // We are switching to this page - refresh it - // if needed. - if (mform != null) - mform.refresh(); - } - } - /** - * Tests if the page is active by asking the parent editor if this page is - * the currently active page. - * - * @return true if the page is currently active, - * false otherwise. - */ - public boolean isActive() { - return this.equals(editor.getActivePageInstance()); - } - /** - * Creates the part control by creating the managed form using the parent - * editor's toolkit. Subclasses should override - * createFormContent(IManagedForm) to populate the form with - * content. - * - * @param parent - * the page parent composite - */ - public void createPartControl(Composite parent) { - ScrolledComposite form = editor.getToolkit().createScrolledForm(parent); - mform = new PageForm(this, form); - BusyIndicator.showWhile(parent.getDisplay(), new Runnable() { - public void run() { - createFormContent(mform); - } - }); - } - /** - * Subclasses should override this method to create content in the form - * hosted in this page. - * - * @param managedForm - * the form hosted in this page. - */ - protected void createFormContent(IManagedForm managedForm) { - } - /** - * Returns the form page control. - * - * @return managed form's control - */ - public Control getPartControl() { - return mform != null ? mform.getForm() : null; - } - /** - * Disposes the managed form. - */ - public void dispose() { - if (mform != null) - mform.dispose(); - } - /** - * Returns the unique identifier that can be used to reference this page. - * - * @return the unique page identifier - */ - public String getId() { - return id; - } - /** - * Returns null- form page has no title image. Subclasses - * may override. - * - * @return null - */ - public Image getTitleImage() { - return null; - } - /** - * Sets the focus by delegating to the managed form. - */ - public void setFocus() { - if (mform != null) - mform.setFocus(); - } - /** - * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor) - */ -// public void doSave(IProgressMonitor monitor) { -// if (mform != null) -// mform.commit(true); -// } - /** - * @see org.eclipse.ui.ISaveablePart#doSaveAs() - */ - public void doSaveAs() { - } - /** - * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed() - */ - public boolean isSaveAsAllowed() { - return false; - } - /** - * Implemented by testing if the managed form is dirty. - * - * @return true if the managed form is dirty, - * false otherwise. - * - * @see org.eclipse.ui.ISaveablePart#isDirty() - */ - public boolean isDirty() { - return mform != null ? mform.isDirty() : false; - } - /** - * Preserves the page index. - * - * @param index - * the assigned page index - */ - public void setIndex(int index) { - this.index = index; - } - /** - * Returns the saved page index. - * - * @return the page index - */ - public int getIndex() { - return index; - } - /** - * Form pages are not editors. - * - * @return false - */ - public boolean isEditor() { - return false; - } - /** - * Attempts to select and reveal the given object by passing the request to - * the managed form. - * - * @param object - * the object to select and reveal in the page if possible. - * @return true if the page has been successfully selected - * and revealed by one of the managed form parts, false - * otherwise. - */ - public boolean selectReveal(Object object) { - if (mform != null) - return mform.setInput(object); - return false; - } - /** - * By default, editor will be allowed to flip the page. - * @return true - */ - public boolean canLeaveThePage() { - return true; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/IFormPage.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/IFormPage.java deleted file mode 100644 index eb08cb59d..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/eclipse/forms/editor/IFormPage.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.argeo.cms.ui.eclipse.forms.editor; -import org.argeo.cms.ui.eclipse.forms.IManagedForm; -import org.eclipse.swt.widgets.Control; -/** - * Interface that all GUI pages need to implement in order - * to be added to FormEditor part. The interface makes - * several assumptions: - *

- *

Existing editors can be wrapped by implementing - * this interface. In this case, 'isEditor' should return true. - * A common editor to wrap in TextEditor that is - * often added to show the raw source code of the file open into - * the multi-page editor. - * - * @since 1.0 - */ -public interface IFormPage { - /** - * @param editor - * the form editor that this page belongs to - */ - void initialize(FormEditor editor); - /** - * Returns the editor this page belongs to. - * - * @return the form editor - */ - FormEditor getEditor(); - /** - * Returns the managed form of this page, unless this is a source page. - * - * @return the managed form or null if this is a source page. - */ - IManagedForm getManagedForm(); - /** - * Indicates whether the page has become the active in the editor. Classes - * that implement this interface may use this method to commit the page (on - * false) or lazily create and/or populate the content on - * true. - * - * @param active - * true if page should be visible, false - * otherwise. - */ - void setActive(boolean active); - /** - * Returns true if page is currently active, false if not. - * - * @return true for active page. - */ - boolean isActive(); - /** - * Tests if the content of the page is in a state that allows the - * editor to flip to another page. Typically, pages that contain - * raw source with syntax errors should not allow editors to - * leave them until errors are corrected. - * @return true if the editor can flip to another page, - * false otherwise. - */ - boolean canLeaveThePage(); - /** - * Returns the control associated with this page. - * - * @return the control of this page if created or null if the - * page has not been shown yet. - */ - Control getPartControl(); - /** - * Page must have a unique id that can be used to show it without knowing - * its relative position in the editor. - * - * @return the unique page identifier - */ - String getId(); - /** - * Returns the position of the page in the editor. - * - * @return the zero-based index of the page in the editor. - */ - int getIndex(); - /** - * Sets the position of the page in the editor. - * - * @param index - * the zero-based index of the page in the editor. - */ - void setIndex(int index); - /** - * Tests whether this page wraps a complete editor that - * can be registered on its own, or represents a page - * that cannot exist outside the multi-page editor context. - * - * @return true if the page wraps an editor, - * false if this is a form page. - */ - boolean isEditor(); - /** - * A hint to bring the provided object into focus. If the object is in a - * tree or table control, select it. If it is shown on a scrollable page, - * ensure that it is visible. If the object is not presented in - * the page, false should be returned to allow another - * page to try. - * - * @param object - * object to select and reveal - * @return true if the request was successful, false - * otherwise. - */ - boolean selectReveal(Object object); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableLink.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableLink.java deleted file mode 100644 index 3c1e8cda5..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableLink.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.argeo.cms.ui.forms; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Editable String that displays a browsable link when read-only */ -public class EditableLink extends EditablePropertyString implements - SwtEditablePart { - private static final long serialVersionUID = 5055000749992803591L; - - private String type; - private String message; - private boolean readOnly; - - public EditableLink(Composite parent, int style, Node node, - String propertyName, String type, String message) - throws RepositoryException { - super(parent, style, node, propertyName, message); - this.message = message; - this.type = type; - - readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY); - if (node.hasProperty(propertyName)) { - this.setStyle(FormStyle.propertyText.style()); - this.setText(node.getProperty(propertyName).getString()); - } else { - this.setStyle(FormStyle.propertyMessage.style()); - this.setText(""); - } - } - - public void setText(String text) { - Control child = getControl(); - if (child instanceof Label) { - Label lbl = (Label) child; - if (EclipseUiUtils.isEmpty(text)) - lbl.setText(message); - else if (readOnly) - setLinkValue(lbl, text); - else - // if canEdit() we put only the value with no link - // to avoid glitches of the edition life cycle - lbl.setText(text); - } else if (child instanceof Text) { - Text txt = (Text) child; - if (EclipseUiUtils.isEmpty(text)) { - txt.setText(""); - txt.setMessage(message); - } else - txt.setText(text); - } - } - - private void setLinkValue(Label lbl, String text) { - if (FormStyle.email.style().equals(type)) - lbl.setText(FormUtils.getMailLink(text)); - else if (FormStyle.phone.style().equals(type)) - lbl.setText(FormUtils.getPhoneLink(text)); - else if (FormStyle.website.style().equals(type)) - lbl.setText(FormUtils.getUrlLink(text)); - else if (FormStyle.facebook.style().equals(type) - || FormStyle.instagram.style().equals(type) - || FormStyle.linkedIn.style().equals(type) - || FormStyle.twitter.style().equals(type)) - lbl.setText(FormUtils.getUrlLink(text)); - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java deleted file mode 100644 index ff8270046..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java +++ /dev/null @@ -1,261 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.ui.widgets.StyledControl; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.events.TraverseEvent; -import org.eclipse.swt.events.TraverseListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Display, add or remove values from a list in a CMS context */ -public class EditableMultiStringProperty extends StyledControl implements SwtEditablePart { - private static final long serialVersionUID = -7044614381252178595L; - - private String propertyName; - private String message; - // TODO implement the ability to provide a list of possible values -// private String[] possibleValues; - private boolean canEdit; - private SelectionListener removeValueSL; - private List values; - - // TODO manage within the CSS - private int rowSpacing = 5; - private int rowMarging = 0; - private int oneValueMargingRight = 5; - private int btnWidth = 16; - private int btnHeight = 16; - private int btnHorizontalIndent = 3; - - public EditableMultiStringProperty(Composite parent, int style, Node node, String propertyName, List values, - String[] possibleValues, String addValueMsg, SelectionListener removeValueSelectionListener) - throws RepositoryException { - super(parent, style, node, true); - - this.propertyName = propertyName; - this.values = values; -// this.possibleValues = new String[] { "Un", "Deux", "Trois" }; - this.message = addValueMsg; - this.canEdit = removeValueSelectionListener != null; - this.removeValueSL = removeValueSelectionListener; - } - - public List getValues() { - return values; - } - - public void setValues(List values) { - this.values = values; - } - - // Row layout items do not need explicit layout data - protected void setControlLayoutData(Control control) { - } - - /** To be overridden */ - protected void setContainerLayoutData(Composite composite) { - composite.setLayoutData(CmsSwtUtils.fillWidth()); - } - - @Override - public Control getControl() { - return super.getControl(); - } - - @Override - protected Control createControl(Composite box, String style) { - Composite row = new Composite(box, SWT.NO_FOCUS); - row.setLayoutData(EclipseUiUtils.fillAll()); - - RowLayout rl = new RowLayout(SWT.HORIZONTAL); - rl.wrap = true; - rl.spacing = rowSpacing; - rl.marginRight = rl.marginLeft = rl.marginBottom = rl.marginTop = rowMarging; - row.setLayout(rl); - - if (values != null) { - for (final String value : values) { - if (canEdit) - createRemovableValue(row, SWT.SINGLE, value); - else - createValueLabel(row, SWT.SINGLE, value); - } - } - - if (!canEdit) - return row; - else if (isEditing()) - return createText(row, style); - else - return createLabel(row, style); - } - - /** - * Override to provide specific layout for the existing values, typically adding - * a pound (#) char for tags or anchor info for browsable links. We assume the - * parent composite already has a layout and it is the caller responsibility to - * apply corresponding layout data - */ - protected Label createValueLabel(Composite parent, int style, String value) { - Label label = new Label(parent, style); - label.setText("#" + value); - CmsSwtUtils.markup(label); - CmsSwtUtils.style(label, FormStyle.propertyText.style()); - return label; - } - - private Composite createRemovableValue(Composite parent, int style, String value) { - Composite valCmp = new Composite(parent, SWT.NO_FOCUS); - GridLayout gl = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false)); - gl.marginRight = oneValueMargingRight; - valCmp.setLayout(gl); - - createValueLabel(valCmp, SWT.WRAP, value); - - Button deleteBtn = new Button(valCmp, SWT.FLAT); - deleteBtn.setData(FormConstants.LINKED_VALUE, value); - deleteBtn.addSelectionListener(removeValueSL); - CmsSwtUtils.style(deleteBtn, FormStyle.delete.style() + FormStyle.BUTTON_SUFFIX); - GridData gd = new GridData(); - gd.heightHint = btnHeight; - gd.widthHint = btnWidth; - gd.horizontalIndent = btnHorizontalIndent; - deleteBtn.setLayoutData(gd); - - return valCmp; - } - - protected Text createText(Composite box, String style) { - final Text text = new Text(box, getStyle()); - // The "add new value" text is not meant to change, so we can set it on - // creation - text.setMessage(message); - CmsSwtUtils.style(text, style); - text.setFocus(); - - text.addTraverseListener(new TraverseListener() { - private static final long serialVersionUID = 1L; - - public void keyTraversed(TraverseEvent e) { - if (e.keyCode == SWT.CR) { - addValue(text); - e.doit = false; - } - } - }); - - // The OK button does not work with the focusOut listener - // because focus out is called before the OK button is pressed - - // // we must call layout() now so that the row data can compute the - // height - // // of the other controls. - // text.getParent().layout(); - // int height = text.getSize().y; - // - // Button okBtn = new Button(box, SWT.BORDER | SWT.PUSH | SWT.BOTTOM); - // okBtn.setText("OK"); - // RowData rd = new RowData(SWT.DEFAULT, height - 2); - // okBtn.setLayoutData(rd); - // - // okBtn.addSelectionListener(new SelectionAdapter() { - // private static final long serialVersionUID = 2780819012423622369L; - // - // @Override - // public void widgetSelected(SelectionEvent e) { - // addValue(text); - // } - // }); - - return text; - } - - /** Performs the real addition, overwrite to make further sanity checks */ - protected void addValue(Text text) { - String value = text.getText(); - String errMsg = null; - - if (EclipseUiUtils.isEmpty(value)) - return; - - if (values.contains(value)) - errMsg = "Dupplicated value: " + value + ", please correct and try again"; - if (errMsg != null) - MessageDialog.openError(this.getShell(), "Addition not allowed", errMsg); - else { - values.add(value); - Composite newCmp = createRemovableValue(text.getParent(), SWT.SINGLE, value); - newCmp.moveAbove(text); - text.setText(""); - newCmp.getParent().layout(); - } - } - - protected Label createLabel(Composite box, String style) { - if (canEdit) { - Label lbl = new Label(box, getStyle()); - lbl.setText(message); - CmsSwtUtils.style(lbl, style); - CmsSwtUtils.markup(lbl); - if (mouseListener != null) - lbl.addMouseListener(mouseListener); - return lbl; - } - return null; - } - - protected void clear(boolean deep) { - Control child = getControl(); - if (deep) - super.clear(deep); - else { - child.getParent().dispose(); - } - } - - public void setText(String text) { - Control child = getControl(); - if (child instanceof Label) { - Label lbl = (Label) child; - if (canEdit) - lbl.setText(text); - else - lbl.setText(""); - } else if (child instanceof Text) { - Text txt = (Text) child; - txt.setText(text); - } - } - - public synchronized void startEditing() { - CmsSwtUtils.style(getControl(), FormStyle.propertyText.style()); -// getControl().setData(STYLE, FormStyle.propertyText.style()); - super.startEditing(); - } - - public synchronized void stopEditing() { - CmsSwtUtils.style(getControl(), FormStyle.propertyMessage.style()); -// getControl().setData(STYLE, FormStyle.propertyMessage.style()); - super.stopEditing(); - } - - public String getPropertyName() { - return propertyName; - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java deleted file mode 100644 index 641f916f2..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java +++ /dev/null @@ -1,298 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.text.DateFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.ui.widgets.StyledControl; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -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.Control; -import org.eclipse.swt.widgets.DateTime; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** CMS form part to display and edit a date */ -public class EditablePropertyDate extends StyledControl implements SwtEditablePart { - private static final long serialVersionUID = 2500215515778162468L; - - // Context - private String propertyName; - private String message; - private DateFormat dateFormat; - - // UI Objects - private Text dateTxt; - private Button openCalBtn; - - // TODO manage within the CSS - private int fieldBtnSpacing = 5; - - /** - * - * @param parent - * @param style - * @param node - * @param propertyName - * @param message - * @param dateFormat provide a {@link DateFormat} as contract to be able to - * read/write dates as strings - * @throws RepositoryException - */ - public EditablePropertyDate(Composite parent, int style, Node node, String propertyName, String message, - DateFormat dateFormat) throws RepositoryException { - super(parent, style, node, false); - - this.propertyName = propertyName; - this.message = message; - this.dateFormat = dateFormat; - - if (node.hasProperty(propertyName)) { - this.setStyle(FormStyle.propertyText.style()); - this.setText(dateFormat.format(node.getProperty(propertyName).getDate().getTime())); - } else { - this.setStyle(FormStyle.propertyMessage.style()); - this.setText(message); - } - } - - public void setText(String text) { - Control child = getControl(); - if (child instanceof Label) { - Label lbl = (Label) child; - if (EclipseUiUtils.isEmpty(text)) - lbl.setText(message); - else - lbl.setText(text); - } else if (child instanceof Text) { - Text txt = (Text) child; - if (EclipseUiUtils.isEmpty(text)) { - txt.setText(""); - } else - txt.setText(text); - } - } - - public synchronized void startEditing() { - // if (dateTxt != null && !dateTxt.isDisposed()) - CmsSwtUtils.style(getControl(), FormStyle.propertyText); -// getControl().setData(STYLE, FormStyle.propertyText.style()); - super.startEditing(); - } - - public synchronized void stopEditing() { - if (EclipseUiUtils.isEmpty(dateTxt.getText())) - CmsSwtUtils.style(getControl(), FormStyle.propertyMessage); -// getControl().setData(STYLE, FormStyle.propertyMessage.style()); - else - CmsSwtUtils.style(getControl(), FormStyle.propertyText); -// getControl().setData(STYLE, FormStyle.propertyText.style()); - super.stopEditing(); - } - - public String getPropertyName() { - return propertyName; - } - - @Override - protected Control createControl(Composite box, String style) { - if (isEditing()) { - return createCustomEditableControl(box, style); - } else - return createLabel(box, style); - } - - protected Label createLabel(Composite box, String style) { - Label lbl = new Label(box, getStyle() | SWT.WRAP); - lbl.setLayoutData(CmsSwtUtils.fillWidth()); - CmsSwtUtils.style(lbl, style); - CmsSwtUtils.markup(lbl); - if (mouseListener != null) - lbl.addMouseListener(mouseListener); - return lbl; - } - - private Control createCustomEditableControl(Composite box, String style) { - box.setLayoutData(CmsSwtUtils.fillWidth()); - Composite dateComposite = new Composite(box, SWT.NONE); - GridLayout gl = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false)); - gl.horizontalSpacing = fieldBtnSpacing; - dateComposite.setLayout(gl); - dateTxt = new Text(dateComposite, SWT.BORDER); - CmsSwtUtils.style(dateTxt, style); - dateTxt.setLayoutData(new GridData(120, SWT.DEFAULT)); - dateTxt.setToolTipText( - "Enter a date with form \"" + FormUtils.DEFAULT_SHORT_DATE_FORMAT + "\" or use the calendar"); - openCalBtn = new Button(dateComposite, SWT.FLAT); - CmsSwtUtils.style(openCalBtn, FormStyle.calendar.style() + FormStyle.BUTTON_SUFFIX); - GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); - gd.heightHint = 17; - openCalBtn.setLayoutData(gd); - // openCalBtn.setImage(PeopleRapImages.CALENDAR_BTN); - - openCalBtn.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 1L; - - public void widgetSelected(SelectionEvent event) { - CalendarPopup popup = new CalendarPopup(dateTxt); - popup.open(); - } - }); - - // dateTxt.addFocusListener(new FocusListener() { - // private static final long serialVersionUID = 1L; - // - // @Override - // public void focusLost(FocusEvent event) { - // String newVal = dateTxt.getText(); - // // Enable reset of the field - // if (FormUtils.notNull(newVal)) - // calendar = null; - // else { - // try { - // Calendar newCal = parseDate(newVal); - // // DateText.this.setText(newCal); - // calendar = newCal; - // } catch (ParseException pe) { - // // Silent. Manage error popup? - // if (calendar != null) - // EditablePropertyDate.this.setText(calendar); - // } - // } - // } - // - // @Override - // public void focusGained(FocusEvent event) { - // } - // }); - return dateTxt; - } - - protected void clear(boolean deep) { - Control child = getControl(); - if (deep || child instanceof Label) - super.clear(deep); - else { - child.getParent().dispose(); - } - } - - /** Enable setting a custom tooltip on the underlying text */ - @Deprecated - public void setToolTipText(String toolTipText) { - dateTxt.setToolTipText(toolTipText); - } - - @Deprecated - /** Enable setting a custom message on the underlying text */ - public void setMessage(String message) { - dateTxt.setMessage(message); - } - - @Deprecated - public void setText(Calendar cal) { - String newValueStr = ""; - if (cal != null) - newValueStr = dateFormat.format(cal.getTime()); - if (!newValueStr.equals(dateTxt.getText())) - dateTxt.setText(newValueStr); - } - - // UTILITIES TO MANAGE THE CALENDAR POPUP - // TODO manage the popup shell in a cleaner way - private class CalendarPopup extends Shell { - private static final long serialVersionUID = 1L; - private DateTime dateTimeCtl; - - public CalendarPopup(Control source) { - super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - populate(); - // Add border and shadow style - CmsSwtUtils.markup(CalendarPopup.this); - CmsSwtUtils.style(CalendarPopup.this, FormStyle.popupCalendar.style()); - pack(); - layout(); - setLocation(source.toDisplay((source.getLocation().x - 2), (source.getSize().y) + 3)); - - addShellListener(new ShellAdapter() { - private static final long serialVersionUID = 5178980294808435833L; - - @Override - public void shellDeactivated(ShellEvent e) { - close(); - dispose(); - } - }); - open(); - } - - private void setProperty() { - // Direct set does not seems to work. investigate - // cal.set(dateTimeCtl.getYear(), dateTimeCtl.getMonth(), - // dateTimeCtl.getDay(), 12, 0); - Calendar cal = new GregorianCalendar(); - cal.set(Calendar.YEAR, dateTimeCtl.getYear()); - cal.set(Calendar.MONTH, dateTimeCtl.getMonth()); - cal.set(Calendar.DAY_OF_MONTH, dateTimeCtl.getDay()); - String dateStr = dateFormat.format(cal.getTime()); - dateTxt.setText(dateStr); - } - - protected void populate() { - setLayout(EclipseUiUtils.noSpaceGridLayout()); - - dateTimeCtl = new DateTime(this, SWT.CALENDAR); - dateTimeCtl.setLayoutData(EclipseUiUtils.fillAll()); - - Calendar calendar = FormUtils.parseDate(dateFormat, dateTxt.getText()); - - if (calendar != null) - dateTimeCtl.setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH)); - - dateTimeCtl.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -8414377364434281112L; - - @Override - public void widgetSelected(SelectionEvent e) { - setProperty(); - } - }); - - dateTimeCtl.addMouseListener(new MouseListener() { - private static final long serialVersionUID = 1L; - - @Override - public void mouseUp(MouseEvent e) { - } - - @Override - public void mouseDown(MouseEvent e) { - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - setProperty(); - close(); - dispose(); - } - }); - } - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java deleted file mode 100644 index f2575e1f9..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.argeo.cms.ui.forms; - -import static org.argeo.cms.ui.forms.FormStyle.propertyMessage; -import static org.argeo.cms.ui.forms.FormStyle.propertyText; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.ui.widgets.EditableText; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Editable String in a CMS context */ -public class EditablePropertyString extends EditableText implements SwtEditablePart { - private static final long serialVersionUID = 5055000749992803591L; - - private String propertyName; - private String message; - - // encode the '&' character in rap - private final static String AMPERSAND = "&"; - private final static String AMPERSAND_REGEX = "&(?![#a-zA-Z0-9]+;)"; - - public EditablePropertyString(Composite parent, int style, Node node, String propertyName, String message) - throws RepositoryException { - super(parent, style, node, true); - //setUseTextAsLabel(true); - this.propertyName = propertyName; - this.message = message; - - if (node.hasProperty(propertyName)) { - this.setStyle(propertyText.style()); - this.setText(node.getProperty(propertyName).getString()); - } else { - this.setStyle(propertyMessage.style()); - this.setText(message + " "); - } - } - - public void setText(String text) { - Control child = getControl(); - if (child instanceof Label) { - Label lbl = (Label) child; - if (EclipseUiUtils.isEmpty(text)) - lbl.setText(message + " "); - else - // TODO enhance this - lbl.setText(text.replaceAll(AMPERSAND_REGEX, AMPERSAND)); - } else if (child instanceof Text) { - Text txt = (Text) child; - if (EclipseUiUtils.isEmpty(text)) { - txt.setText(""); - txt.setMessage(message + " "); - } else - txt.setText(text.replaceAll("
", "\n")); - } - } - - public synchronized void startEditing() { - CmsSwtUtils.style(getControl(), FormStyle.propertyText); - super.startEditing(); - } - - public synchronized void stopEditing() { - if (EclipseUiUtils.isEmpty(((Text) getControl()).getText())) - CmsSwtUtils.style(getControl(), FormStyle.propertyMessage); - else - CmsSwtUtils.style(getControl(), FormStyle.propertyText); - super.stopEditing(); - } - - public String getPropertyName() { - return propertyName; - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormConstants.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormConstants.java deleted file mode 100644 index fe9f7e7d7..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormConstants.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.argeo.cms.ui.forms; - -/** Constants used in the various CMS Forms */ -public interface FormConstants { - // DATAKEYS - public final static String LINKED_VALUE = "LinkedValue"; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormEditorHeader.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormEditorHeader.java deleted file mode 100644 index a75c19150..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormEditorHeader.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.util.Observable; -import java.util.Observer; - -import javax.jcr.Node; - -import org.argeo.api.cms.ux.CmsEditable; -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; - -/** Add life cycle management abilities to an editable form page */ -public class FormEditorHeader implements SelectionListener, Observer { - private static final long serialVersionUID = 7392898696542484282L; - - // private final Node context; - private final CmsEditable cmsEditable; - private Button publishBtn; - - // Should we provide here the ability to switch from read only to edition - // mode? - // private Button editBtn; - // private boolean readOnly; - - // TODO add information about the current node status, typically if it is - // dirty or not - - private Composite parent; - private Composite display; - private Object layoutData; - - public FormEditorHeader(Composite parent, int style, Node context, - CmsEditable cmsEditable) { - this.cmsEditable = cmsEditable; - this.parent = parent; - // readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY); - // this.context = context; - if (this.cmsEditable instanceof Observable) - ((Observable) this.cmsEditable).addObserver(this); - refresh(); - } - - public void setLayoutData(Object layoutData) { - this.layoutData = layoutData; - if (display != null && !display.isDisposed()) - display.setLayoutData(layoutData); - } - - protected void refresh() { - if (display != null && !display.isDisposed()) - display.dispose(); - - display = new Composite(parent, SWT.NONE); - display.setLayoutData(layoutData); - - CmsSwtUtils.style(display, FormStyle.header.style()); - display.setBackgroundMode(SWT.INHERIT_FORCE); - - display.setLayout(CmsSwtUtils.noSpaceGridLayout()); - - publishBtn = createSimpleBtn(display, getPublishButtonLabel()); - display.moveAbove(null); - parent.layout(); - } - - private Button createSimpleBtn(Composite parent, String label) { - Button button = new Button(parent, SWT.FLAT | SWT.PUSH); - button.setText(label); - CmsSwtUtils.style(button, FormStyle.header.style()); - button.addSelectionListener(this); - return button; - } - - private String getPublishButtonLabel() { - // Rather check if the current node differs from what has been - // previously committed - // For the time being, we always reach here, the underlying CmsEditable - // is always editing. - if (cmsEditable.isEditing()) - return " Publish "; - else - return " Edit "; - } - - @Override - public void widgetSelected(SelectionEvent e) { - if (e.getSource() == publishBtn) { - // For the time being, the underlying CmsEditable - // is always editing when we reach this point - if (cmsEditable.isEditing()) { - // we always leave the node in a check outed state - cmsEditable.stopEditing(); - cmsEditable.startEditing(); - } else { - cmsEditable.startEditing(); - } - } - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - - @Override - public void update(Observable o, Object arg) { - if (o == cmsEditable) { - refresh(); - } - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java deleted file mode 100644 index 1888055fc..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java +++ /dev/null @@ -1,608 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.io.IOException; -import java.io.InputStream; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; - -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.api.cms.ux.CmsEditable; -import org.argeo.api.cms.ux.CmsImageManager; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.ui.viewers.AbstractPageViewer; -import org.argeo.cms.ui.viewers.Section; -import org.argeo.cms.ui.viewers.SectionPart; -import org.argeo.cms.ui.widgets.EditableImage; -import org.argeo.cms.ui.widgets.Img; -import org.argeo.cms.ui.widgets.StyledControl; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.rap.fileupload.FileDetails; -import org.eclipse.rap.fileupload.FileUploadEvent; -import org.eclipse.rap.fileupload.FileUploadHandler; -import org.eclipse.rap.fileupload.FileUploadListener; -import org.eclipse.rap.fileupload.FileUploadReceiver; -import org.eclipse.rap.rwt.service.ServerPushSession; -import org.eclipse.rap.rwt.widgets.FileUpload; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.FormAttachment; -import org.eclipse.swt.layout.FormData; -import org.eclipse.swt.layout.FormLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Manage life cycle of a form page that is linked to a given node */ -public class FormPageViewer extends AbstractPageViewer { - private final static CmsLog log = CmsLog.getLog(FormPageViewer.class); - private static final long serialVersionUID = 5277789504209413500L; - - private final Section mainSection; - - // TODO manage within the CSS - private Integer labelColWidth = null; - private int rowLayoutHSpacing = 8; - - // Context cached in the viewer - // The reference to translate from text to calendar and reverse - private DateFormat dateFormat = new SimpleDateFormat(FormUtils.DEFAULT_SHORT_DATE_FORMAT); - private CmsImageManager imageManager; - private FileUploadListener fileUploadListener; - - public FormPageViewer(Section mainSection, int style, CmsEditable cmsEditable) throws RepositoryException { - super(mainSection, style, cmsEditable); - this.mainSection = mainSection; - - if (getCmsEditable().canEdit()) { - fileUploadListener = new FUL(); - } - } - - @Override - protected void prepare(SwtEditablePart part, Object caretPosition) { - if (part instanceof Img) { - ((Img) part).setFileUploadListener(fileUploadListener); - } - } - - /** To be overridden.Save the edited part. */ - protected void save(SwtEditablePart part) throws RepositoryException { - Node node = null; - if (part instanceof EditableMultiStringProperty) { - EditableMultiStringProperty ept = (EditableMultiStringProperty) part; - // SWT : View - List values = ept.getValues(); - // JCR : Model - node = ept.getNode(); - String propName = ept.getPropertyName(); - if (values.isEmpty()) { - if (node.hasProperty(propName)) - node.getProperty(propName).remove(); - } else { - node.setProperty(propName, values.toArray(new String[0])); - } - // => Viewer : Controller - } else if (part instanceof EditablePropertyString) { - EditablePropertyString ept = (EditablePropertyString) part; - // SWT : View - String txt = ((Text) ept.getControl()).getText(); - // JCR : Model - node = ept.getNode(); - String propName = ept.getPropertyName(); - if (EclipseUiUtils.isEmpty(txt)) { - if (node.hasProperty(propName)) - node.getProperty(propName).remove(); - } else { - setPropertySilently(node, propName, txt); - // node.setProperty(propName, txt); - } - // node.getSession().save(); - // => Viewer : Controller - } else if (part instanceof EditablePropertyDate) { - EditablePropertyDate ept = (EditablePropertyDate) part; - Calendar cal = FormUtils.parseDate(dateFormat, ((Text) ept.getControl()).getText()); - node = ept.getNode(); - String propName = ept.getPropertyName(); - if (cal == null) { - if (node.hasProperty(propName)) - node.getProperty(propName).remove(); - } else { - node.setProperty(propName, cal); - } - // node.getSession().save(); - // => Viewer : Controller - } - // TODO: make this configurable, sometimes we do not want to save the - // current session at this stage - if (node != null && node.getSession().hasPendingChanges()) { - JcrUtils.updateLastModified(node, true); - node.getSession().save(); - } - } - - @Override - protected void updateContent(SwtEditablePart part) throws RepositoryException { - if (part instanceof EditableMultiStringProperty) { - EditableMultiStringProperty ept = (EditableMultiStringProperty) part; - // SWT : View - Node node = ept.getNode(); - String propName = ept.getPropertyName(); - List valStrings = new ArrayList(); - if (node.hasProperty(propName)) { - Value[] values = node.getProperty(propName).getValues(); - for (Value val : values) - valStrings.add(val.getString()); - } - ept.setValues(valStrings); - } else if (part instanceof EditablePropertyString) { - // || part instanceof EditableLink - EditablePropertyString ept = (EditablePropertyString) part; - // JCR : Model - Node node = ept.getNode(); - String propName = ept.getPropertyName(); - if (node.hasProperty(propName)) { - String value = node.getProperty(propName).getString(); - ept.setText(value); - } else - ept.setText(""); - // => Viewer : Controller - } else if (part instanceof EditablePropertyDate) { - EditablePropertyDate ept = (EditablePropertyDate) part; - // JCR : Model - Node node = ept.getNode(); - String propName = ept.getPropertyName(); - if (node.hasProperty(propName)) - ept.setText(dateFormat.format(node.getProperty(propName).getDate().getTime())); - else - ept.setText(""); - } else if (part instanceof SectionPart) { - SectionPart sectionPart = (SectionPart) part; - Node partNode = sectionPart.getNode(); - // use control AFTER setting style, since it may have been reset - if (part instanceof EditableImage) { - EditableImage editableImage = (EditableImage) part; - imageManager().load(partNode, part.getControl(), editableImage.getPreferredImageSize()); - } - } - } - - // FILE UPLOAD LISTENER - protected class FUL implements FileUploadListener { - - public FUL() { - } - - public void uploadProgress(FileUploadEvent event) { - // TODO Monitor upload progress - } - - public void uploadFailed(FileUploadEvent event) { - throw new IllegalStateException("Upload failed " + event, event.getException()); - } - - public void uploadFinished(FileUploadEvent event) { - for (FileDetails file : event.getFileDetails()) { - if (log.isDebugEnabled()) - log.debug("Received: " + file.getFileName()); - } - mainSection.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - saveEdit(); - } - }); - FileUploadHandler uploadHandler = (FileUploadHandler) event.getSource(); - uploadHandler.dispose(); - } - } - - // FOCUS OUT LISTENER - protected FocusListener createFocusListener() { - return new FocusOutListener(); - } - - private class FocusOutListener implements FocusListener { - private static final long serialVersionUID = -6069205786732354186L; - - @Override - public void focusLost(FocusEvent event) { - saveEdit(); - } - - @Override - public void focusGained(FocusEvent event) { - // does nothing; - } - } - - // MOUSE LISTENER - @Override - protected MouseListener createMouseListener() { - return new ML(); - } - - private class ML extends MouseAdapter { - private static final long serialVersionUID = 8526890859876770905L; - - @Override - public void mouseDoubleClick(MouseEvent e) { - if (e.button == 1) { - Control source = (Control) e.getSource(); - if (getCmsEditable().canEdit()) { - if (getCmsEditable().isEditing() && !(getEdited() instanceof Img)) { - if (source == mainSection) - return; - SwtEditablePart part = findDataParent(source); - upload(part); - } else { - getCmsEditable().startEditing(); - } - } - } - } - - @Override - public void mouseDown(MouseEvent e) { - if (getCmsEditable().isEditing()) { - if (e.button == 1) { - Control source = (Control) e.getSource(); - SwtEditablePart composite = findDataParent(source); - Point point = new Point(e.x, e.y); - if (!(composite instanceof Img)) - edit(composite, source.toDisplay(point)); - } else if (e.button == 3) { - // EditablePart composite = findDataParent((Control) e - // .getSource()); - // if (styledTools != null) - // styledTools.show(composite, new Point(e.x, e.y)); - } - } - } - - protected synchronized void upload(SwtEditablePart part) { - if (part instanceof SectionPart) { - if (part instanceof Img) { - if (getEdited() == part) - return; - edit(part, null); - layout(part.getControl()); - } - } - } - } - - @Override - public Control getControl() { - return mainSection; - } - - protected CmsImageManager imageManager() { - if (imageManager == null) - imageManager = (CmsImageManager) CmsSwtUtils.getCmsView(mainSection).getImageManager(); - return imageManager; - } - - // LOCAL UI HELPERS - protected Section createSectionIfNeeded(Composite body, Node node) throws RepositoryException { - Section section = null; - if (node != null) { - section = new Section(body, SWT.NO_FOCUS, node); - section.setLayoutData(CmsSwtUtils.fillWidth()); - section.setLayout(CmsSwtUtils.noSpaceGridLayout()); - } - return section; - } - - protected void createSimpleLT(Composite bodyRow, Node node, String propName, String label, String msg) - throws RepositoryException { - if (getCmsEditable().canEdit() || node.hasProperty(propName)) { - createPropertyLbl(bodyRow, label); - EditablePropertyString eps = new EditablePropertyString(bodyRow, SWT.WRAP | SWT.LEFT, node, propName, msg); - eps.setMouseListener(getMouseListener()); - eps.setFocusListener(getFocusListener()); - eps.setLayoutData(CmsSwtUtils.fillWidth()); - } - } - - protected void createMultiStringLT(Composite bodyRow, Node node, String propName, String label, String msg) - throws RepositoryException { - boolean canEdit = getCmsEditable().canEdit(); - if (canEdit || node.hasProperty(propName)) { - createPropertyLbl(bodyRow, label); - - List valueStrings = new ArrayList(); - - if (node.hasProperty(propName)) { - Value[] values = node.getProperty(propName).getValues(); - for (Value value : values) - valueStrings.add(value.getString()); - } - - // TODO use a drop down to display possible values to the end user - EditableMultiStringProperty emsp = new EditableMultiStringProperty(bodyRow, SWT.SINGLE | SWT.LEAD, node, - propName, valueStrings, new String[] { "Implement this" }, msg, - canEdit ? getRemoveValueSelListener() : null); - addListeners(emsp); - // emsp.setMouseListener(getMouseListener()); - emsp.setStyle(FormStyle.propertyMessage.style()); - emsp.setLayoutData(CmsSwtUtils.fillWidth()); - } - } - - protected Label createPropertyLbl(Composite parent, String value) { - return createPropertyLbl(parent, value, SWT.NONE); - } - - protected Label createPropertyLbl(Composite parent, String value, int vAlign) { - // boolean isSmall = CmsView.getCmsView(parent).getUxContext().isSmall(); - Label label = new Label(parent, SWT.LEAD | SWT.WRAP); - label.setText(value + " "); - CmsSwtUtils.style(label, FormStyle.propertyLabel.style()); - GridData gd = new GridData(SWT.LEAD, vAlign, false, false); - if (labelColWidth != null) - gd.widthHint = labelColWidth; - label.setLayoutData(gd); - return label; - } - - protected Label newStyledLabel(Composite parent, String style, String value) { - Label label = new Label(parent, SWT.NONE); - label.setText(value); - CmsSwtUtils.style(label, style); - return label; - } - - protected Composite createRowLayoutComposite(Composite parent) throws RepositoryException { - Composite bodyRow = new Composite(parent, SWT.NO_FOCUS); - bodyRow.setLayoutData(CmsSwtUtils.fillWidth()); - RowLayout rl = new RowLayout(SWT.WRAP); - rl.type = SWT.HORIZONTAL; - rl.spacing = rowLayoutHSpacing; - rl.marginHeight = rl.marginWidth = 0; - rl.marginTop = rl.marginBottom = rl.marginLeft = rl.marginRight = 0; - bodyRow.setLayout(rl); - return bodyRow; - } - - protected Composite createAddImgComposite(final Section section, Composite parent, final Node parentNode) - throws RepositoryException { - - Composite body = new Composite(parent, SWT.NO_FOCUS); - body.setLayout(new GridLayout()); - - FormFileUploadReceiver receiver = new FormFileUploadReceiver(section, parentNode, null); - final FileUploadHandler currentUploadHandler = new FileUploadHandler(receiver); - if (fileUploadListener != null) - currentUploadHandler.addUploadListener(fileUploadListener); - - // Button creation - final FileUpload fileUpload = new FileUpload(body, SWT.BORDER); - fileUpload.setText("Import an image"); - fileUpload.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); - fileUpload.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 4869523412991968759L; - - @Override - public void widgetSelected(SelectionEvent e) { - ServerPushSession pushSession = new ServerPushSession(); - pushSession.start(); - String uploadURL = currentUploadHandler.getUploadUrl(); - fileUpload.submit(uploadURL); - } - }); - - return body; - } - - protected class FormFileUploadReceiver extends FileUploadReceiver { - - private Node context; - private Section section; - private String name; - - public FormFileUploadReceiver(Section section, Node context, String name) { - this.context = context; - this.section = section; - this.name = name; - } - - @Override - public void receive(InputStream stream, FileDetails details) throws IOException { - - if (name == null) - name = details.getFileName(); - - // TODO clean image name more carefully - String cleanedName = name.replaceAll("[^a-zA-Z0-9-.]", ""); - // We add a unique prefix to workaround the cache issue: when - // deleting and re-adding a new image with same name, the end user - // browser will use the cache and the image will remain unchanged - // for a while - cleanedName = System.currentTimeMillis() % 100000 + "_" + cleanedName; - - imageManager().uploadImage(context, context, cleanedName, stream, details.getContentType()); - // TODO clean refresh strategy - section.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - try { - FormPageViewer.this.refresh(section); - section.layout(); - section.getParent().layout(); - } catch (RepositoryException re) { - throw new JcrException("Unable to refresh " + "image section for " + context, re); - } - } - }); - } - } - - protected void addListeners(StyledControl control) { - control.setMouseListener(getMouseListener()); - control.setFocusListener(getFocusListener()); - } - - protected Img createImgComposite(Composite parent, Node node, Point preferredSize) throws RepositoryException { - Img img = new Img(parent, SWT.NONE, node, new Cms2DSize(preferredSize.x, preferredSize.y)) { - private static final long serialVersionUID = 1297900641952417540L; - - @Override - protected void setContainerLayoutData(Composite composite) { - composite.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT)); - } - - @Override - protected void setControlLayoutData(Control control) { - control.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT)); - } - }; - img.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT)); - updateContent(img); - addListeners(img); - return img; - } - - protected Composite addDeleteAbility(final Section section, final Node sessionNode, int topWeight, - int rightWeight) { - Composite comp = new Composite(section, SWT.NONE); - comp.setLayoutData(CmsSwtUtils.fillAll()); - comp.setLayout(new FormLayout()); - - // The body to be populated - Composite body = new Composite(comp, SWT.NO_FOCUS); - body.setLayoutData(EclipseUiUtils.fillFormData()); - - if (getCmsEditable().canEdit()) { - // the delete button - Button deleteBtn = new Button(comp, SWT.FLAT); - CmsSwtUtils.style(deleteBtn, FormStyle.deleteOverlay.style()); - FormData formData = new FormData(); - formData.right = new FormAttachment(rightWeight, 0); - formData.top = new FormAttachment(topWeight, 0); - deleteBtn.setLayoutData(formData); - deleteBtn.moveAbove(body); - - deleteBtn.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 4304223543657238462L; - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - if (MessageDialog.openConfirm(section.getShell(), "Confirm deletion", - "Are you really you want to remove this?")) { - Session session; - try { - session = sessionNode.getSession(); - Section parSection = section.getParentSection(); - sessionNode.remove(); - session.save(); - refresh(parSection); - layout(parSection); - } catch (RepositoryException re) { - throw new JcrException("Unable to delete " + sessionNode, re); - } - - } - - } - }); - } - return body; - } - -// // LOCAL HELPERS FOR NODE MANAGEMENT -// private Node getOrCreateNode(Node parent, String nodeName, String nodeType) throws RepositoryException { -// Node node = null; -// if (getCmsEditable().canEdit() && !parent.hasNode(nodeName)) { -// node = JcrUtils.mkdirs(parent, nodeName, nodeType); -// parent.getSession().save(); -// } -// -// if (getCmsEditable().canEdit() || parent.hasNode(nodeName)) -// node = parent.getNode(nodeName); -// -// return node; -// } - - private SelectionListener getRemoveValueSelListener() { - return new SelectionAdapter() { - private static final long serialVersionUID = 9022259089907445195L; - - @Override - public void widgetSelected(SelectionEvent e) { - Object source = e.getSource(); - if (source instanceof Button) { - Button btn = (Button) source; - Object obj = btn.getData(FormConstants.LINKED_VALUE); - SwtEditablePart ep = findDataParent(btn); - if (ep != null && ep instanceof EditableMultiStringProperty) { - EditableMultiStringProperty emsp = (EditableMultiStringProperty) ep; - List values = emsp.getValues(); - if (values.contains(obj)) { - values.remove(values.indexOf(obj)); - emsp.setValues(values); - try { - save(emsp); - // TODO workaround to force refresh - edit(emsp, 0); - cancelEdit(); - } catch (RepositoryException e1) { - throw new JcrException("Unable to remove value " + obj, e1); - } - layout(emsp); - } - } - } - } - }; - } - - protected void setPropertySilently(Node node, String propName, String value) throws RepositoryException { - try { - // TODO Clean this: - // Format strings to replace \n - value = value.replaceAll("\n", "
"); - // Do not make the update if validation fails - try { - MarkupValidatorCopy.getInstance().validate(value); - } catch (Exception e) { - log.warn("Cannot set [" + value + "] on prop " + propName + "of " + node - + ", String cannot be validated - " + e.getMessage()); - return; - } - // TODO check if the newly created property is of the correct type, - // otherwise the property will be silently created with a STRING - // property type. - node.setProperty(propName, value); - } catch (ValueFormatException vfe) { - log.warn("Cannot set [" + value + "] on prop " + propName + "of " + node + " - " + vfe.getMessage()); - } - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormStyle.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormStyle.java deleted file mode 100644 index 709ecd024..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormStyle.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.argeo.cms.ui.forms; - -import org.argeo.api.cms.ux.CmsStyle; - -/** Syles used */ -public enum FormStyle implements CmsStyle { - // Main - form, title, - // main part - header, headerBtn, headerCombo, section, sectionHeader, - // Property fields - propertyLabel, propertyText, propertyMessage, errorMessage, - // Date - popupCalendar, - // Buttons - starred, unstarred, starOverlay, editOverlay, deleteOverlay, updateOverlay, deleteOverlaySmall, calendar, delete, - // Contacts - email, address, phone, website, - // Social Media - facebook, twitter, linkedIn, instagram; - - @Override - public String getClassPrefix() { - return "argeo-form"; - } - - // TODO clean button style management - public final static String BUTTON_SUFFIX = "_btn"; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormUtils.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormUtils.java deleted file mode 100644 index eeafabbe1..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/FormUtils.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.CmsView; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.jface.fieldassist.ControlDecoration; -import org.eclipse.jface.fieldassist.FieldDecorationRegistry; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Utilitary methods to ease implementation of CMS forms */ -public class FormUtils { - private final static CmsLog log = CmsLog.getLog(FormUtils.class); - - public final static String DEFAULT_SHORT_DATE_FORMAT = "dd/MM/yyyy"; - - /** Best effort to convert a String to a calendar. Fails silently */ - public static Calendar parseDate(DateFormat dateFormat, String calStr) { - Calendar cal = null; - if (EclipseUiUtils.notEmpty(calStr)) { - try { - Date date = dateFormat.parse(calStr); - cal = new GregorianCalendar(); - cal.setTime(date); - } catch (ParseException pe) { - // Silent - log.warn("Unable to parse date: " + calStr + " - msg: " - + pe.getMessage()); - } - } - return cal; - } - - /** Add a double click listener on tables that display a JCR node list */ - public static void addCanonicalDoubleClickListener(final TableViewer v) { - v.addDoubleClickListener(new IDoubleClickListener() { - - @Override - public void doubleClick(DoubleClickEvent event) { - CmsView cmsView = CmsUiUtils.getCmsView(); - Node node = (Node) ((IStructuredSelection) event.getSelection()) - .getFirstElement(); - try { - cmsView.navigateTo(node.getPath()); - } catch (RepositoryException e) { - throw new CmsException("Unable to get path for node " - + node + " before calling navigateTo(path)", e); - } - } - }); - } - - // MANAGE ERROR DECORATION - - public static ControlDecoration addDecoration(final Text text) { - final ControlDecoration dynDecoration = new ControlDecoration(text, - SWT.LEFT); - Image icon = getDecorationImage(FieldDecorationRegistry.DEC_ERROR); - dynDecoration.setImage(icon); - dynDecoration.setMarginWidth(3); - dynDecoration.hide(); - return dynDecoration; - } - - public static void refreshDecoration(Text text, ControlDecoration deco, - boolean isValid, boolean clean) { - if (isValid || clean) { - text.setBackground(null); - deco.hide(); - } else { - text.setBackground(new Color(text.getDisplay(), 250, 200, 150)); - deco.show(); - } - } - - public static Image getDecorationImage(String image) { - FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault(); - return registry.getFieldDecoration(image).getImage(); - } - - public static void addCompulsoryDecoration(Label label) { - final ControlDecoration dynDecoration = new ControlDecoration(label, - SWT.RIGHT | SWT.TOP); - Image icon = getDecorationImage(FieldDecorationRegistry.DEC_REQUIRED); - dynDecoration.setImage(icon); - dynDecoration.setMarginWidth(3); - } - - // TODO the read only generation of read only links for various contact type - // should be factorised in the cms Utils. - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able phone number - */ - public static String getPhoneLink(String value) { - return getPhoneLink(value, value); - } - - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able phone number - * - * @param value - * @param label - * a potentially distinct label - * @return the link - */ - public static String getPhoneLink(String value, String label) { - StringBuilder builder = new StringBuilder(); - builder.append("").append(label) - .append(""); - return builder.toString(); - } - - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able mail - */ - public static String getMailLink(String value) { - return getMailLink(value, value); - } - - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able mail - * - * @param value - * @param label - * a potentially distinct label - * @return the link - */ - public static String getMailLink(String value, String label) { - StringBuilder builder = new StringBuilder(); - value = replaceAmpersand(value); - builder.append("").append(label).append(""); - return builder.toString(); - } - - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able link - */ - public static String getUrlLink(String value) { - return getUrlLink(value, value); - } - - /** - * Creates the read-only HTML snippet to display in a label with styling - * enabled in order to provide a click-able link - */ - public static String getUrlLink(String value, String label) { - StringBuilder builder = new StringBuilder(); - value = replaceAmpersand(value); - label = replaceAmpersand(label); - if (!(value.startsWith("http://") || value.startsWith("https://"))) - value = "http://" + value; - builder.append("" + label + ""); - return builder.toString(); - } - - private static String AMPERSAND = "&"; - - /** - * Cleans a String by replacing any '&' by its HTML encoding '&#38;' to - * avoid SAXParseException while rendering HTML with RWT - */ - public static String replaceAmpersand(String value) { - value = value.replaceAll("&(?![#a-zA-Z0-9]+;)", AMPERSAND); - return value; - } - - // Prevents instantiation - private FormUtils() { - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/MarkupValidatorCopy.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/MarkupValidatorCopy.java deleted file mode 100644 index 3f588d1ea..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/MarkupValidatorCopy.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.argeo.cms.ui.forms; - -import java.io.StringReader; -import java.text.MessageFormat; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.eclipse.rap.rwt.SingletonUtil; -import org.eclipse.swt.widgets.Widget; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.helpers.DefaultHandler; - -/** - * Copy of RAP v2.3 since it is in an internal package. - */ -class MarkupValidatorCopy { - - // Used by Eclipse Scout project - public static final String MARKUP_VALIDATION_DISABLED = "org.eclipse.rap.rwt.markupValidationDisabled"; - - private static final String DTD = createDTD(); - private static final Map SUPPORTED_ELEMENTS = createSupportedElementsMap(); - private final SAXParser saxParser; - - public static MarkupValidatorCopy getInstance() { - return SingletonUtil.getSessionInstance(MarkupValidatorCopy.class); - } - - public MarkupValidatorCopy() { - saxParser = createSAXParser(); - } - - public void validate(String text) { - StringBuilder markup = new StringBuilder(); - markup.append(DTD); - markup.append(""); - markup.append(text); - markup.append(""); - InputSource inputSource = new InputSource(new StringReader(markup.toString())); - try { - saxParser.parse(inputSource, new MarkupHandler()); - } catch (RuntimeException exception) { - throw exception; - } catch (Exception exception) { - throw new IllegalArgumentException("Failed to parse markup text", exception); - } - } - - public static boolean isValidationDisabledFor(Widget widget) { - return Boolean.TRUE.equals(widget.getData(MARKUP_VALIDATION_DISABLED)); - } - - private static SAXParser createSAXParser() { - SAXParser result = null; - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - try { - result = parserFactory.newSAXParser(); - } catch (Exception exception) { - throw new RuntimeException("Failed to create SAX parser", exception); - } - return result; - } - - private static String createDTD() { - StringBuilder result = new StringBuilder(); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append(""); - result.append("]>"); - return result.toString(); - } - - private static Map createSupportedElementsMap() { - Map result = new HashMap(); - result.put("html", new String[0]); - result.put("br", new String[0]); - result.put("b", new String[] { "style" }); - result.put("strong", new String[] { "style" }); - result.put("i", new String[] { "style" }); - result.put("em", new String[] { "style" }); - result.put("sub", new String[] { "style" }); - result.put("sup", new String[] { "style" }); - result.put("big", new String[] { "style" }); - result.put("small", new String[] { "style" }); - result.put("del", new String[] { "style" }); - result.put("ins", new String[] { "style" }); - result.put("code", new String[] { "style" }); - result.put("samp", new String[] { "style" }); - result.put("kbd", new String[] { "style" }); - result.put("var", new String[] { "style" }); - result.put("cite", new String[] { "style" }); - result.put("dfn", new String[] { "style" }); - result.put("q", new String[] { "style" }); - result.put("abbr", new String[] { "style", "title" }); - result.put("span", new String[] { "style" }); - result.put("img", new String[] { "style", "src", "width", "height", "title", "alt" }); - result.put("a", new String[] { "style", "href", "target", "title" }); - return result; - } - - private static class MarkupHandler extends DefaultHandler { - - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) { - checkSupportedElements(name, attributes); - checkSupportedAttributes(name, attributes); - checkMandatoryAttributes(name, attributes); - } - - private static void checkSupportedElements(String elementName, Attributes attributes) { - if (!SUPPORTED_ELEMENTS.containsKey(elementName)) { - throw new IllegalArgumentException("Unsupported element in markup text: " + elementName); - } - } - - private static void checkSupportedAttributes(String elementName, Attributes attributes) { - if (attributes.getLength() > 0) { - List supportedAttributes = Arrays.asList(SUPPORTED_ELEMENTS.get(elementName)); - int index = 0; - String attributeName = attributes.getQName(index); - while (attributeName != null) { - if (!supportedAttributes.contains(attributeName)) { - String message = "Unsupported attribute \"{0}\" for element \"{1}\" in markup text"; - message = MessageFormat.format(message, new Object[] { attributeName, elementName }); - throw new IllegalArgumentException(message); - } - index++; - attributeName = attributes.getQName(index); - } - } - } - - private static void checkMandatoryAttributes(String elementName, Attributes attributes) { - checkIntAttribute(elementName, attributes, "img", "width"); - checkIntAttribute(elementName, attributes, "img", "height"); - } - - private static void checkIntAttribute(String elementName, Attributes attributes, String checkedElementName, - String checkedAttributeName) { - if (checkedElementName.equals(elementName)) { - String attribute = attributes.getValue(checkedAttributeName); - try { - Integer.parseInt(attribute); - } catch (NumberFormatException exception) { - String message = "Mandatory attribute \"{0}\" for element \"{1}\" is missing or not a valid integer"; - Object[] arguments = new Object[] { checkedAttributeName, checkedElementName }; - message = MessageFormat.format(message, arguments); - throw new IllegalArgumentException(message); - } - } - } - - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/package-info.java deleted file mode 100644 index 5f954c1c4..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/forms/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo CMS forms, based on SWT/JFace. */ -package org.argeo.cms.ui.forms; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java deleted file mode 100644 index d9c1c1221..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java +++ /dev/null @@ -1,524 +0,0 @@ -package org.argeo.cms.ui.fs; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.spi.FileSystemProvider; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.Session; - -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.fs.FileIconNameLabelProvider; -import org.argeo.eclipse.ui.fs.FsTableViewer; -import org.argeo.eclipse.ui.fs.FsUiConstants; -import org.argeo.eclipse.ui.fs.FsUiUtils; -import org.argeo.eclipse.ui.fs.NioFileLabelProvider; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowData; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.Text; - -/** - * Default CMS browser composite: a sashForm layout with bookmarks at the left - * hand side, a simple table in the middle and an overview at right hand side. - */ -public class CmsFsBrowser extends Composite { - // private final static Log log = LogFactory.getLog(CmsFsBrowser.class); - private static final long serialVersionUID = -40347919096946585L; - - private final FileSystemProvider nodeFileSystemProvider; - private final Node currentBaseContext; - - // UI Parts for the browser - private Composite leftPannelCmp; - private Composite filterCmp; - private Text filterTxt; - private FsTableViewer directoryDisplayViewer; - private Composite rightPannelCmp; - - private FsContextMenu contextMenu; - - // Local context (this composite is state full) - private Path initialPath; - private Path currDisplayedFolder; - private Path currSelected; - - // local variables (to be cleaned) - private int bookmarkColWith = 500; - - /* - * WARNING: unfinalised implementation of the mechanism to retrieve base - * paths - */ - - private final static String NODE_PREFIX = "node://"; - - private String getCurrentHomePath() { - Session session = null; - try { - Repository repo = currentBaseContext.getSession().getRepository(); - session = CurrentUser.tryAs(() -> repo.login()); - String homepath = CmsJcrUtils.getUserHome(session).getPath(); - return homepath; - } catch (Exception e) { - throw new CmsException("Cannot retrieve Current User Home Path", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - protected Path[] getMyFilesPath() { - // return Paths.get(System.getProperty("user.dir")); - String currHomeUriStr = NODE_PREFIX + getCurrentHomePath(); - try { - URI uri = new URI(currHomeUriStr); - FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri); - if (fileSystem == null) { - PrivilegedExceptionAction pea = new PrivilegedExceptionAction() { - @Override - public FileSystem run() throws Exception { - return nodeFileSystemProvider.newFileSystem(uri, null); - } - - }; - fileSystem = CurrentUser.tryAs(pea); - } - Path[] paths = { fileSystem.getPath(getCurrentHomePath()), fileSystem.getPath("/") }; - return paths; - } catch (URISyntaxException | PrivilegedActionException e) { - throw new RuntimeException("unable to initialise home file system for " + currHomeUriStr, e); - } - } - - private Path[] getMyGroupsFilesPath() { - // TODO - Path[] paths = { Paths.get(System.getProperty("user.dir")), Paths.get("/tmp") }; - return paths; - } - - private Path[] getMyBookmarks() { - // TODO - Path[] paths = { Paths.get(System.getProperty("user.dir")), Paths.get("/tmp"), Paths.get("/opt") }; - return paths; - } - - /* End of warning */ - - public CmsFsBrowser(Composite parent, int style, Node context, FileSystemProvider fileSystemProvider) { - super(parent, style); - this.nodeFileSystemProvider = fileSystemProvider; - this.currentBaseContext = context; - - this.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - SashForm form = new SashForm(this, SWT.HORIZONTAL); - - leftPannelCmp = new Composite(form, SWT.NO_FOCUS); - // Bookmarks are still static - populateBookmarks(leftPannelCmp); - - Composite centerCmp = new Composite(form, SWT.BORDER | SWT.NO_FOCUS); - createDisplay(centerCmp); - - rightPannelCmp = new Composite(form, SWT.NO_FOCUS); - - form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - form.setWeights(new int[] { 15, 40, 20 }); - } - - void refresh() { - modifyFilter(false); - // also refresh bookmarks and groups - } - - private void createDisplay(final Composite parent) { - parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - // top filter - filterCmp = new Composite(parent, SWT.NO_FOCUS); - filterCmp.setLayoutData(EclipseUiUtils.fillWidth()); - addFilterPanel(filterCmp); - - // Main display - directoryDisplayViewer = new FsTableViewer(parent, SWT.MULTI); - List colDefs = new ArrayList<>(); - colDefs.add(new ColumnDefinition(new FileIconNameLabelProvider(), "Name", 250)); - colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_SIZE), "Size", 100)); - colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_TYPE), "Type", 150)); - colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_LAST_MODIFIED), - "Last modified", 400)); - final Table table = directoryDisplayViewer.configureDefaultTable(colDefs); - table.setLayoutData(EclipseUiUtils.fillAll()); - - // table.addKeyListener(new KeyListener() { - // private static final long serialVersionUID = -8083424284436715709L; - // - // @Override - // public void keyReleased(KeyEvent e) { - // } - // - // @Override - // public void keyPressed(KeyEvent e) { - // if (log.isDebugEnabled()) - // log.debug("Key event received: " + e.keyCode); - // IStructuredSelection selection = (IStructuredSelection) - // directoryDisplayViewer.getSelection(); - // Path selected = null; - // if (!selection.isEmpty()) - // selected = ((Path) selection.getFirstElement()); - // if (e.keyCode == SWT.CR) { - // if (!Files.isDirectory(selected)) - // return; - // if (selected != null) { - // currDisplayedFolder = selected; - // directoryDisplayViewer.setInput(currDisplayedFolder, "*"); - // } - // } else if (e.keyCode == SWT.BS) { - // currDisplayedFolder = currDisplayedFolder.getParent(); - // directoryDisplayViewer.setInput(currDisplayedFolder, "*"); - // directoryDisplayViewer.getTable().setFocus(); - // } - // } - // }); - - directoryDisplayViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) directoryDisplayViewer.getSelection(); - Path selected = null; - if (selection.isEmpty()) - setSelected(null); - else - selected = ((Path) selection.getFirstElement()); - if (selected != null) { - // TODO manage multiple selection - setSelected(selected); - } - } - }); - - directoryDisplayViewer.addDoubleClickListener(new IDoubleClickListener() { - @Override - public void doubleClick(DoubleClickEvent event) { - IStructuredSelection selection = (IStructuredSelection) directoryDisplayViewer.getSelection(); - Path selected = null; - if (!selection.isEmpty()) - selected = ((Path) selection.getFirstElement()); - if (selected != null) { - if (!Files.isDirectory(selected)) - return; - setInput(selected); - } - } - }); - - // The context menu - contextMenu = new FsContextMenu(this); - - table.addMouseListener(new MouseAdapter() { - private static final long serialVersionUID = 6737579410648595940L; - - @Override - public void mouseDown(MouseEvent e) { - if (e.button == 3) { - // contextMenu.setCurrFolderPath(currDisplayedFolder); - contextMenu.show(table, new Point(e.x, e.y), currDisplayedFolder); - } - } - }); - } - - private void addPathElementBtn(Path path) { - Button elemBtn = new Button(filterCmp, SWT.PUSH); - String nameStr; - if (path.toString().equals("/")) - nameStr = "[jcr:root]"; - else - nameStr = path.getFileName().toString(); - elemBtn.setText(nameStr + " >> "); - CmsSwtUtils.style(elemBtn, FsStyles.BREAD_CRUMB_BTN); - elemBtn.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -4103695476023480651L; - - @Override - public void widgetSelected(SelectionEvent e) { - setInput(path); - } - }); - } - - public void setInput(Path path) { - if (path.equals(currDisplayedFolder)) - return; - currDisplayedFolder = path; - - Path diff = initialPath.relativize(currDisplayedFolder); - - for (Control child : filterCmp.getChildren()) - if (!child.equals(filterTxt)) - child.dispose(); - - addPathElementBtn(initialPath); - Path currTarget = initialPath; - if (!diff.toString().equals("")) - for (Path pathElem : diff) { - currTarget = currTarget.resolve(pathElem); - addPathElementBtn(currTarget); - } - - filterTxt.setText(""); - filterTxt.moveBelow(null); - setSelected(null); - filterCmp.getParent().layout(true, true); - } - - private void setSelected(Path path) { - currSelected = path; - setOverviewInput(path); - } - - public Viewer getViewer() { - return directoryDisplayViewer; - } - - private void populateBookmarks(Composite parent) { - CmsSwtUtils.clear(parent); - parent.setLayout(new GridLayout()); - ISelectionChangedListener selList = new BookmarksSelChangeListener(); - - FsTableViewer homeViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); - Table table = homeViewer.configureDefaultSingleColumnTable(bookmarkColWith); - GridData gd = EclipseUiUtils.fillWidth(); - gd.horizontalIndent = 10; - table.setLayoutData(gd); - homeViewer.addSelectionChangedListener(selList); - homeViewer.setPathsInput(getMyFilesPath()); - - appendTitle(parent, "Shared files"); - FsTableViewer groupsViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); - table = groupsViewer.configureDefaultSingleColumnTable(bookmarkColWith); - gd = EclipseUiUtils.fillWidth(); - gd.horizontalIndent = 10; - table.setLayoutData(gd); - groupsViewer.addSelectionChangedListener(selList); - groupsViewer.setPathsInput(getMyGroupsFilesPath()); - - appendTitle(parent, "My bookmarks"); - FsTableViewer bookmarksViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); - table = bookmarksViewer.configureDefaultSingleColumnTable(bookmarkColWith); - gd = EclipseUiUtils.fillWidth(); - gd.horizontalIndent = 10; - table.setLayoutData(gd); - bookmarksViewer.addSelectionChangedListener(selList); - bookmarksViewer.setPathsInput(getMyBookmarks()); - } - - /** - * Recreates the content of the box that displays information about the - * current selected Path. - */ - private void setOverviewInput(Path path) { - try { - EclipseUiUtils.clear(rightPannelCmp); - rightPannelCmp.setLayout(new GridLayout()); - if (path != null) { - // if (isImg(context)) { - // EditableImage image = new Img(parent, RIGHT, context, - // imageWidth); - // image.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, - // true, false, - // 2, 1)); - // } - - Label contextL = new Label(rightPannelCmp, SWT.NONE); - contextL.setText(path.getFileName().toString()); - contextL.setFont(EclipseUiUtils.getBoldFont(rightPannelCmp)); - addProperty(rightPannelCmp, "Last modified", Files.getLastModifiedTime(path).toString()); - // addProperty(rightPannelCmp, "Owner", - // Files.getOwner(path).getName()); - if (Files.isDirectory(path)) { - addProperty(rightPannelCmp, "Type", "Folder"); - } else { - String mimeType = Files.probeContentType(path); - if (EclipseUiUtils.isEmpty(mimeType)) - mimeType = "Unknown"; - addProperty(rightPannelCmp, "Type", mimeType); - addProperty(rightPannelCmp, "Size", FsUiUtils.humanReadableByteCount(Files.size(path), false)); - } - } - rightPannelCmp.layout(true, true); - } catch (IOException e) { - throw new CmsException("Cannot display details for " + path.toString(), e); - } - } - - private void addFilterPanel(Composite parent) { - RowLayout rl = new RowLayout(SWT.HORIZONTAL); - rl.wrap = true; - parent.setLayout(rl); - // parent.setLayout(EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, - // false))); - - filterTxt = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL); - filterTxt.setMessage("Search current folder"); - filterTxt.setLayoutData(new RowData(250, SWT.DEFAULT)); - filterTxt.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = 1L; - - public void modifyText(ModifyEvent event) { - modifyFilter(false); - } - }); - filterTxt.addKeyListener(new KeyListener() { - private static final long serialVersionUID = 2533535233583035527L; - - @Override - public void keyReleased(KeyEvent e) { - } - - @Override - public void keyPressed(KeyEvent e) { - // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0; - // // boolean altPressed = (e.stateMask & SWT.ALT) != 0; - // FilterEntitiesVirtualTable currTable = null; - // if (currEdited != null) { - // FilterEntitiesVirtualTable table = - // browserCols.get(currEdited); - // if (table != null && !table.isDisposed()) - // currTable = table; - // } - // - // if (e.keyCode == SWT.ARROW_DOWN) - // currTable.setFocus(); - // else if (e.keyCode == SWT.BS) { - // if (filterTxt.getText().equals("") - // && !(currEdited.getNameCount() == 1 || - // currEdited.equals(initialPath))) { - // Path oldEdited = currEdited; - // Path parentPath = currEdited.getParent(); - // setEdited(parentPath); - // if (browserCols.containsKey(parentPath)) - // browserCols.get(parentPath).setSelected(oldEdited); - // filterTxt.setFocus(); - // e.doit = false; - // } - // } else if (e.keyCode == SWT.TAB && !shiftPressed) { - // Path uniqueChild = getOnlyChild(currEdited, - // filterTxt.getText()); - // if (uniqueChild != null) { - // // Highlight the unique chosen child - // currTable.setSelected(uniqueChild); - // setEdited(uniqueChild); - // } - // filterTxt.setFocus(); - // e.doit = false; - // } - } - }); - } - - private Path getOnlyChild(Path parent, String filter) { - try (DirectoryStream stream = Files.newDirectoryStream(currDisplayedFolder, filter + "*")) { - Path uniqueChild = null; - boolean moreThanOne = false; - loop: for (Path entry : stream) { - if (uniqueChild == null) { - uniqueChild = entry; - } else { - moreThanOne = true; - break loop; - } - } - if (!moreThanOne) - return uniqueChild; - return null; - } catch (IOException ioe) { - throw new CmsException( - "Unable to determine unique child existence and get it under " + parent + " with filter " + filter, - ioe); - } - } - - private void modifyFilter(boolean fromOutside) { - if (!fromOutside) - if (currDisplayedFolder != null) { - String filter = filterTxt.getText() + "*"; - directoryDisplayViewer.setInput(currDisplayedFolder, filter); - } - } - - private class BookmarksSelChangeListener implements ISelectionChangedListener { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - if (selection.isEmpty()) - return; - else { - Path newSelected = (Path) selection.getFirstElement(); - if (newSelected.equals(currDisplayedFolder) && newSelected.equals(initialPath)) - return; - initialPath = newSelected; - setInput(newSelected); - } - } - } - - // Simplify UI implementation - private void addProperty(Composite parent, String propName, String value) { - Label contextL = new Label(parent, SWT.NONE); - contextL.setText(propName + ": " + value); - } - - private Label appendTitle(Composite parent, String value) { - Label titleLbl = new Label(parent, SWT.NONE); - titleLbl.setText(value); - titleLbl.setFont(EclipseUiUtils.getBoldFont(parent)); - GridData gd = EclipseUiUtils.fillWidth(); - gd.horizontalIndent = 5; - gd.verticalIndent = 5; - titleLbl.setLayoutData(gd); - return titleLbl; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FileDrop.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FileDrop.java deleted file mode 100644 index e875b5a3d..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FileDrop.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.argeo.cms.ui.fs; - -import java.io.IOException; -import java.io.InputStream; - -import org.argeo.api.cms.CmsLog; -import org.argeo.eclipse.ui.specific.FileDropAdapter; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DropTarget; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.widgets.Control; - -/** Allows a control to receive file drops. */ -public class FileDrop { - private final static CmsLog log = CmsLog.getLog(FileDrop.class); - - public void createDropTarget(Control control) { - FileDropAdapter fileDropAdapter = new FileDropAdapter() { - @Override - protected void processUpload(InputStream in, String fileName, String contentType) throws IOException { - if (log.isDebugEnabled()) - log.debug("Process upload of " + fileName + " (" + contentType + ")"); - processFileUpload(in, fileName, contentType); - } - }; - DropTarget dropTarget = new DropTarget(control, DND.DROP_MOVE | DND.DROP_COPY); - fileDropAdapter.prepareDropTarget(control, dropTarget); - } - - public void handleFileDrop(Control control, DropTargetEvent event) { - } - - /** Executed in UI thread */ - protected void processFileUpload(InputStream in, String fileName, String contentType) throws IOException { - - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java deleted file mode 100644 index 1fb3c2a05..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java +++ /dev/null @@ -1,383 +0,0 @@ -package org.argeo.cms.ui.fs; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.io.IOUtils; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -/** Generic popup context menu to manage NIO Path in a Viewer. */ -public class FsContextMenu extends Shell { - private static final long serialVersionUID = -9120261153509855795L; - - private final static CmsLog log = CmsLog.getLog(FsContextMenu.class); - - // Default known actions - public final static String ACTION_ID_CREATE_FOLDER = "createFolder"; - public final static String ACTION_ID_BOOKMARK_FOLDER = "bookmarkFolder"; - public final static String ACTION_ID_SHARE_FOLDER = "shareFolder"; - public final static String ACTION_ID_DOWNLOAD_FOLDER = "downloadFolder"; - public final static String ACTION_ID_DELETE = "delete"; - public final static String ACTION_ID_UPLOAD_FILE = "uploadFiles"; - public final static String ACTION_ID_OPEN = "open"; - - // Local context - private final CmsFsBrowser browser; - // private final Viewer viewer; - private final static String KEY_ACTION_ID = "actionId"; - private final static String[] DEFAULT_ACTIONS = { ACTION_ID_CREATE_FOLDER, ACTION_ID_BOOKMARK_FOLDER, - ACTION_ID_SHARE_FOLDER, ACTION_ID_DOWNLOAD_FOLDER, ACTION_ID_DELETE, ACTION_ID_UPLOAD_FILE, - ACTION_ID_OPEN }; - private Map actionButtons = new HashMap(); - - private Path currFolderPath; - - public FsContextMenu(CmsFsBrowser browser) { // Viewer viewer, Display - // display) { - super(browser.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - this.browser = browser; - setLayout(EclipseUiUtils.noSpaceGridLayout()); - - Composite boxCmp = new Composite(this, SWT.NO_FOCUS | SWT.BORDER); - boxCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); - CmsSwtUtils.style(boxCmp, FsStyles.CONTEXT_MENU_BOX); - createContextMenu(boxCmp); - - addShellListener(new ActionsShellListener()); - } - - protected void createContextMenu(Composite boxCmp) { - ActionsSelListener asl = new ActionsSelListener(); - for (String actionId : DEFAULT_ACTIONS) { - Button btn = new Button(boxCmp, SWT.FLAT | SWT.PUSH | SWT.LEAD); - btn.setText(getLabel(actionId)); - btn.setLayoutData(EclipseUiUtils.fillWidth()); - CmsSwtUtils.markup(btn); - CmsSwtUtils.style(btn, actionId + FsStyles.BUTTON_SUFFIX); - btn.setData(KEY_ACTION_ID, actionId); - btn.addSelectionListener(asl); - actionButtons.put(actionId, btn); - } - } - - protected String getLabel(String actionId) { - switch (actionId) { - case ACTION_ID_CREATE_FOLDER: - return "Create Folder"; - case ACTION_ID_BOOKMARK_FOLDER: - return "Bookmark Folder"; - case ACTION_ID_SHARE_FOLDER: - return "Share Folder"; - case ACTION_ID_DOWNLOAD_FOLDER: - return "Download as zip archive"; - case ACTION_ID_DELETE: - return "Delete"; - case ACTION_ID_UPLOAD_FILE: - return "Upload Files"; - case ACTION_ID_OPEN: - return "Open"; - default: - throw new IllegalArgumentException("Unknown action ID " + actionId); - } - } - - protected void aboutToShow(Control source, Point location) { - IStructuredSelection selection = ((IStructuredSelection) browser.getViewer().getSelection()); - boolean emptySel = true; - boolean multiSel = false; - boolean isFolder = true; - if (selection != null && !selection.isEmpty()) { - emptySel = false; - multiSel = selection.size() > 1; - if (!multiSel && selection.getFirstElement() instanceof Path) { - isFolder = Files.isDirectory((Path) selection.getFirstElement()); - } - } - if (emptySel) { - setVisible(true, ACTION_ID_CREATE_FOLDER, ACTION_ID_UPLOAD_FILE); - setVisible(false, ACTION_ID_SHARE_FOLDER, ACTION_ID_DOWNLOAD_FOLDER, ACTION_ID_DELETE, ACTION_ID_OPEN, - // to be implemented - ACTION_ID_BOOKMARK_FOLDER); - } else if (multiSel) { - setVisible(true, ACTION_ID_CREATE_FOLDER, ACTION_ID_UPLOAD_FILE, ACTION_ID_DELETE); - setVisible(false, ACTION_ID_SHARE_FOLDER, ACTION_ID_DOWNLOAD_FOLDER, ACTION_ID_OPEN, - // to be implemented - ACTION_ID_BOOKMARK_FOLDER); - } else if (isFolder) { - setVisible(true, ACTION_ID_CREATE_FOLDER, ACTION_ID_UPLOAD_FILE, ACTION_ID_DELETE); - setVisible(false, ACTION_ID_OPEN, - // to be implemented - ACTION_ID_SHARE_FOLDER, ACTION_ID_DOWNLOAD_FOLDER, ACTION_ID_BOOKMARK_FOLDER); - } else { - setVisible(true, ACTION_ID_CREATE_FOLDER, ACTION_ID_UPLOAD_FILE, ACTION_ID_OPEN, ACTION_ID_DELETE); - setVisible(false, ACTION_ID_SHARE_FOLDER, ACTION_ID_DOWNLOAD_FOLDER, - // to be implemented - ACTION_ID_BOOKMARK_FOLDER); - } - } - - private void setVisible(boolean visible, String... buttonIds) { - for (String id : buttonIds) { - Button button = actionButtons.get(id); - button.setVisible(visible); - GridData gd = (GridData) button.getLayoutData(); - gd.heightHint = visible ? SWT.DEFAULT : 0; - } - } - - public void show(Control source, Point location, Path currFolderPath) { - if (isVisible()) - setVisible(false); - // TODO find a better way to retrieve the parent path (cannot be deduced - // from table content because it will fail on an empty folder) - this.currFolderPath = currFolderPath; - aboutToShow(source, location); - pack(); - layout(); - if (source instanceof Control) - setLocation(((Control) source).toDisplay(location.x, location.y)); - open(); - } - - class StyleButton extends Label { - private static final long serialVersionUID = 7731102609123946115L; - - public StyleButton(Composite parent, int swtStyle) { - super(parent, swtStyle); - } - - } - - // class ActionsMouseListener extends MouseAdapter { - // private static final long serialVersionUID = -1041871937815812149L; - // - // @Override - // public void mouseDown(MouseEvent e) { - // Object eventSource = e.getSource(); - // if (e.button == 1) { - // if (eventSource instanceof Button) { - // Button pressedBtn = (Button) eventSource; - // String actionId = (String) pressedBtn.getData(KEY_ACTION_ID); - // switch (actionId) { - // case ACTION_ID_CREATE_FOLDER: - // createFolder(); - // break; - // case ACTION_ID_DELETE: - // deleteItems(); - // break; - // default: - // throw new IllegalArgumentException("Unimplemented action " + actionId); - // // case ACTION_ID_SHARE_FOLDER: - // // return "Share Folder"; - // // case ACTION_ID_DOWNLOAD_FOLDER: - // // return "Download as zip archive"; - // // case ACTION_ID_UPLOAD_FILE: - // // return "Upload Files"; - // // case ACTION_ID_OPEN: - // // return "Open"; - // } - // } - // } - // viewer.getControl().setFocus(); - // // setVisible(false); - // } - // } - - class ActionsSelListener extends SelectionAdapter { - private static final long serialVersionUID = -1041871937815812149L; - - @Override - public void widgetSelected(SelectionEvent e) { - Object eventSource = e.getSource(); - if (eventSource instanceof Button) { - Button pressedBtn = (Button) eventSource; - String actionId = (String) pressedBtn.getData(KEY_ACTION_ID); - switch (actionId) { - case ACTION_ID_CREATE_FOLDER: - createFolder(); - break; - case ACTION_ID_DELETE: - deleteItems(); - break; - case ACTION_ID_OPEN: - openFile(); - break; - case ACTION_ID_UPLOAD_FILE: - uploadFiles(); - break; - default: - throw new IllegalArgumentException("Unimplemented action " + actionId); - // case ACTION_ID_SHARE_FOLDER: - // return "Share Folder"; - // case ACTION_ID_DOWNLOAD_FOLDER: - // return "Download as zip archive"; - // case ACTION_ID_OPEN: - // return "Open"; - } - } - browser.setFocus(); - // viewer.getControl().setFocus(); - // setVisible(false); - - } - } - - class ActionsShellListener extends org.eclipse.swt.events.ShellAdapter { - private static final long serialVersionUID = -5092341449523150827L; - - @Override - public void shellDeactivated(ShellEvent e) { - setVisible(false); - } - } - - private void openFile() { - log.warn("Implement single sourced, workbench independant \"Open File\" action"); - } - - private void deleteItems() { - IStructuredSelection selection = ((IStructuredSelection) browser.getViewer().getSelection()); - if (selection.isEmpty()) - return; - - StringBuilder builder = new StringBuilder(); - @SuppressWarnings("unchecked") - Iterator iterator = selection.iterator(); - List paths = new ArrayList<>(); - - while (iterator.hasNext()) { - Path path = (Path) iterator.next(); - builder.append(path.getFileName() + ", "); - paths.add(path); - } - String msg = "You are about to delete following elements: " + builder.substring(0, builder.length() - 2) - + ". Are you sure?"; - if (MessageDialog.openConfirm(this, "Confirm deletion", msg)) { - for (Path path : paths) { - try { - // Might have already been deleted if we are in a tree - Files.deleteIfExists(path); - } catch (IOException e) { - throw new CmsException("Cannot delete path " + path, e); - } - } - browser.refresh(); - } - } - - private void createFolder() { - String msg = "Please provide a name."; - String name = SingleValue.ask("Create folder", msg); - // TODO enhance check of name validity - if (EclipseUiUtils.notEmpty(name)) { - try { - Path child = currFolderPath.resolve(name); - if (Files.exists(child)) - throw new CmsException("An item with name " + name + " already exists at " - + currFolderPath.toString() + ", cannot create"); - else - Files.createDirectories(child); - browser.refresh(); - } catch (IOException e) { - throw new CmsException("Cannot create folder " + name + " at " + currFolderPath.toString(), e); - } - } - } - - private void uploadFiles() { - try { - FileDialog dialog = new FileDialog(browser.getShell(), SWT.MULTI); - dialog.setText("Choose one or more files to upload"); - - if (EclipseUiUtils.notEmpty(dialog.open())) { - String[] names = dialog.getFileNames(); - // Workaround small differences between RAP and RCP - // 1. returned names are absolute path on RAP and - // relative in RCP - // 2. in RCP we must use getFilterPath that does not - // exists on RAP - Method filterMethod = null; - Path parPath = null; - try { - filterMethod = dialog.getClass().getDeclaredMethod("getFilterPath"); - String filterPath = (String) filterMethod.invoke(dialog); - parPath = Paths.get(filterPath); - } catch (NoSuchMethodException nsme) { // RAP - } - if (names.length == 0) - return; - else { - loop: for (String name : names) { - Path tmpPath = Paths.get(name); - if (parPath != null) - tmpPath = parPath.resolve(tmpPath); - if (Files.exists(tmpPath)) { - URI uri = tmpPath.toUri(); - String uriStr = uri.toString(); - - if (Files.isDirectory(tmpPath)) { - MessageDialog.openError(browser.getShell(), "Unimplemented directory import", - "Upload of directories in the system is not yet implemented"); - continue loop; - } - Path targetPath = currFolderPath.resolve(tmpPath.getFileName().toString()); - InputStream in = null; - try { - in = new ByteArrayInputStream(Files.readAllBytes(tmpPath)); - Files.copy(in, targetPath); - Files.delete(tmpPath); - } finally { - IOUtils.closeQuietly(in); - } - if (log.isDebugEnabled()) - log.debug("copied uploaded file " + uriStr + " to " + targetPath.toString()); - } else { - String msg = "Cannot copy tmp file from " + tmpPath.toString(); - if (parPath != null) - msg += "\nPlease remember that file upload fails when choosing files from the \"Recently Used\" bookmarks on some OS"; - MessageDialog.openError(browser.getShell(), "Missing file", msg); - continue loop; - } - } - browser.refresh(); - } - } - } catch (Exception e) { - e.printStackTrace(); - MessageDialog.openError(getShell(), "Upload has failed", "Cannot import files to " + currFolderPath); - } - } - - public void setCurrFolderPath(Path currFolderPath) { - this.currFolderPath = currFolderPath; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsStyles.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsStyles.java deleted file mode 100644 index 9ae319282..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/FsStyles.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.ui.fs; - -/** FS Ui specific CSS styles */ -public interface FsStyles { - String BREAD_CRUMB_BTN = "breadCrumb_btn"; - String CONTEXT_MENU_BOX = "contextMenu_box"; - String BUTTON_SUFFIX = "_btn"; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/package-info.java deleted file mode 100644 index 6a6c27286..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/fs/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** SWT/JFace file system components. */ -package org.argeo.cms.ui.fs; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/Activator.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/Activator.java deleted file mode 100644 index e10da3aed..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/Activator.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.argeo.cms.ui.internal; - -import org.argeo.api.cms.CmsState; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; - -public class Activator implements BundleActivator { - - // avoid dependency to RWT OSGi - private final static String CONTEXT_NAME_PROP = "contextName"; - - private static ServiceTracker nodeState; - - // @Override - public void start(BundleContext bc) throws Exception { - // UI -// bc.registerService(ApplicationConfiguration.class, new MaintenanceUi(), -// LangUtils.dico(CONTEXT_NAME_PROP, "system")); -// bc.registerService(ApplicationConfiguration.class, new UserUi(), LangUtils.dico(CONTEXT_NAME_PROP, "user")); - - nodeState = new ServiceTracker<>(bc, CmsState.class, null); - nodeState.open(); - } - - @Override - public void stop(BundleContext context) throws Exception { - if (nodeState != null) { - nodeState.close(); - nodeState = null; - } - } - - public static CmsState getNodeState() { - return nodeState.getService(); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java deleted file mode 100644 index ea0abdf5d..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.argeo.cms.ui.internal; - -import java.util.ArrayList; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsException; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -@Deprecated -class JcrContentProvider implements ITreeContentProvider { - private static final long serialVersionUID = -1333678161322488674L; - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (newInput == null) - return; - if (!(newInput instanceof Node)) - throw new CmsException("Input " + newInput + " must be a node"); - } - - @Override - public Object[] getElements(Object inputElement) { - try { - Node node = (Node) inputElement; - ArrayList arr = new ArrayList(); - NodeIterator nit = node.getNodes(); - while (nit.hasNext()) { - arr.add(nit.nextNode()); - } - return arr.toArray(); - } catch (RepositoryException e) { - throw new CmsException("Cannot get elements", e); - } - } - - @Override - public Object[] getChildren(Object parentElement) { - try { - Node node = (Node) parentElement; - ArrayList arr = new ArrayList(); - NodeIterator nit = node.getNodes(); - while (nit.hasNext()) { - arr.add(nit.nextNode()); - } - return arr.toArray(); - } catch (RepositoryException e) { - throw new CmsException("Cannot get elements", e); - } - } - - @Override - public Object getParent(Object element) { - try { - Node node = (Node) element; - if (node.getName().equals("")) - return null; - else - return node.getParent(); - } catch (RepositoryException e) { - throw new CmsException("Cannot get elements", e); - } - } - - @Override - public boolean hasChildren(Object element) { - try { - Node node = (Node) element; - return node.hasNodes(); - } catch (RepositoryException e) { - throw new CmsException("Cannot get elements", e); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrFileUploadReceiver.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrFileUploadReceiver.java deleted file mode 100644 index 60bb42b46..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/JcrFileUploadReceiver.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.argeo.cms.ui.internal; - -import static javax.jcr.nodetype.NodeType.NT_FILE; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.FilenameUtils; -import org.argeo.api.cms.ux.CmsImageManager; -import org.argeo.cms.ui.widgets.Img; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.rap.fileupload.FileDetails; -import org.eclipse.rap.fileupload.FileUploadReceiver; - -public class JcrFileUploadReceiver extends FileUploadReceiver { - private Img img; - private final Node parentNode; - private final String nodeName; - private final CmsImageManager imageManager; - - /** If nodeName is null, use the uploaded file name */ - public JcrFileUploadReceiver(Img img, Node parentNode, String nodeName, CmsImageManager imageManager) { - super(); - this.img = img; - this.parentNode = parentNode; - this.nodeName = nodeName; - this.imageManager = imageManager; - } - - @Override - public void receive(InputStream stream, FileDetails details) throws IOException { - try { - String fileName = nodeName != null ? nodeName : details.getFileName(); - String contentType = details.getContentType(); - if (isImage(details.getFileName(), contentType)) { - imageManager.uploadImage(img.getNode(),parentNode, fileName, stream, contentType); - return; - } - - Node fileNode; - if (parentNode.hasNode(fileName)) { - fileNode = parentNode.getNode(fileName); - if (!fileNode.isNodeType(NT_FILE)) - fileNode.remove(); - } - fileNode = JcrUtils.copyStreamAsFile(parentNode, fileName, stream); - - if (contentType != null) { - fileNode.addMixin(NodeType.MIX_MIMETYPE); - fileNode.setProperty(Property.JCR_MIMETYPE, contentType); - } - processNewFile(fileNode); - fileNode.getSession().save(); - } catch (RepositoryException e) { - throw new JcrException("Cannot receive " + details, e); - } - } - - protected Boolean isImage(String fileName, String contentType) { - String ext = FilenameUtils.getExtension(fileName); - return ext != null && (ext.equals("png") || ext.equalsIgnoreCase("jpg")); - } - - protected void processNewFile(Node node) { - - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/SimpleEditableImage.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/SimpleEditableImage.java deleted file mode 100644 index 6162a74bf..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/internal/SimpleEditableImage.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.argeo.cms.ui.internal; - -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.cms.ui.widgets.EditableImage; -import org.argeo.cms.ux.AbstractImageManager; -import org.argeo.cms.ux.CmsUxUtils; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Text; - -/** NOT working yet. */ -public class SimpleEditableImage extends EditableImage { - private static final long serialVersionUID = -5689145523114022890L; - - private String src; - private Cms2DSize imageSize; - - public SimpleEditableImage(Composite parent, int swtStyle) { - super(parent, swtStyle); - // load(getControl()); - getParent().layout(); - } - - public SimpleEditableImage(Composite parent, int swtStyle, String src, Cms2DSize imageSize) { - super(parent, swtStyle); - this.src = src; - this.imageSize = imageSize; - } - - @Override - protected Control createControl(Composite box, String style) { - if (isEditing()) { - return createText(box, style); - } else { - return createLabel(box, style); - } - } - - protected String createImgTag() throws RepositoryException { - String imgTag; - if (src != null) - imgTag = CmsUxUtils.img(src, imageSize); - else - imgTag = CmsUiUtils.noImg(imageSize != null ? imageSize : AbstractImageManager.NO_IMAGE_SIZE); - return imgTag; - } - - protected Text createText(Composite box, String style) { - Text text = new Text(box, getStyle()); - CmsSwtUtils.style(text, style); - return text; - } - - public String getSrc() { - return src; - } - - public void setSrc(String src) { - this.src = src; - } - - public Cms2DSize getImageSize() { - return imageSize; - } - - public void setImageSize(Cms2DSize imageSize) { - this.imageSize = imageSize; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/DefaultRepositoryRegister.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/DefaultRepositoryRegister.java deleted file mode 100644 index 380634118..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/DefaultRepositoryRegister.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.Collections; -import java.util.Map; -import java.util.Observable; -import java.util.TreeMap; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; - -public class DefaultRepositoryRegister extends Observable implements RepositoryRegister { - /** Key for a JCR repository alias */ - private final static String CN = CmsConstants.CN; - /** Key for a JCR repository URI */ - // public final static String JCR_REPOSITORY_URI = "argeo.jcr.repository.uri"; - private final static CmsLog log = CmsLog.getLog(DefaultRepositoryRegister.class); - - /** Read only map which will be directly exposed. */ - private Map repositories = Collections.unmodifiableMap(new TreeMap()); - - @SuppressWarnings("rawtypes") - public synchronized Repository getRepository(Map parameters) throws RepositoryException { - if (!parameters.containsKey(CN)) - throw new RepositoryException("Parameter " + CN + " has to be defined."); - String alias = parameters.get(CN).toString(); - if (!repositories.containsKey(alias)) - throw new RepositoryException("No repository registered with alias " + alias); - - return repositories.get(alias); - } - - /** Access to the read-only map */ - public synchronized Map getRepositories() { - return repositories; - } - - /** Registers a service, typically called when OSGi services are bound. */ - @SuppressWarnings("rawtypes") - public synchronized void register(Repository repository, Map properties) { - String alias; - if (properties == null || !properties.containsKey(CN)) { - log.warn("Cannot register a repository if no " + CN + " property is specified."); - return; - } - alias = properties.get(CN).toString(); - Map map = new TreeMap(repositories); - map.put(alias, repository); - repositories = Collections.unmodifiableMap(map); - setChanged(); - notifyObservers(alias); - } - - /** Unregisters a service, typically called when OSGi services are unbound. */ - @SuppressWarnings("rawtypes") - public synchronized void unregister(Repository repository, Map properties) { - // TODO: also check bean name? - if (properties == null || !properties.containsKey(CN)) { - log.warn("Cannot unregister a repository without property " + CN); - return; - } - - String alias = properties.get(CN).toString(); - Map map = new TreeMap(repositories); - if (map.remove(alias) == null) { - log.warn("No repository was registered with alias " + alias); - return; - } - repositories = Collections.unmodifiableMap(map); - setChanged(); - notifyObservers(alias); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/FullVersioningTreeContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/FullVersioningTreeContentProvider.java deleted file mode 100644 index 0f7ee7735..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/FullVersioningTreeContentProvider.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.VersionManager; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Display some version information of a JCR full versionable node in a tree - * like structure - */ -public class FullVersioningTreeContentProvider implements ITreeContentProvider { - private static final long serialVersionUID = 8691772509491211112L; - - /** - * Sends back the first level of the Tree. input element must be a single - * node object - */ - public Object[] getElements(Object inputElement) { - try { - Node rootNode = (Node) inputElement; - String curPath = rootNode.getPath(); - VersionManager vm = rootNode.getSession().getWorkspace() - .getVersionManager(); - - VersionHistory vh = vm.getVersionHistory(curPath); - List result = new ArrayList(); - VersionIterator vi = vh.getAllLinearVersions(); - - while (vi.hasNext()) { - result.add(vi.nextVersion()); - } - return result.toArray(); - } catch (RepositoryException re) { - throw new EclipseUiException( - "Unexpected error while getting version elements", re); - } - } - - public Object[] getChildren(Object parentElement) { - try { - if (parentElement instanceof Version) { - List tmp = new ArrayList(); - tmp.add(((Version) parentElement).getFrozenNode()); - return tmp.toArray(); - } - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error while getting child " - + "node for version element", re); - } - return null; - } - - public Object getParent(Object element) { - try { - // this will not work in a simpleVersionning environment, parent is - // not a node. - if (element instanceof Node - && ((Node) element).isNodeType(NodeType.NT_FROZEN_NODE)) { - Node node = (Node) element; - return node.getParent(); - } else - return null; - } catch (RepositoryException e) { - return null; - } - } - - public boolean hasChildren(Object element) { - try { - if (element instanceof Version) - return true; - else if (element instanceof Node) - return ((Node) element).hasNodes(); - else - return false; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check children of " + element, e); - } - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java deleted file mode 100644 index b36acc368..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.argeo.cms.ui.jcr.model.RepositoriesElem; -import org.argeo.cms.ui.jcr.model.RepositoryElem; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; - -/** Useful methods to manage the JCR Browser */ -public class JcrBrowserUtils { - - public static String getPropertyTypeAsString(Property prop) { - try { - return PropertyType.nameFromValue(prop.getType()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check type for " + prop, e); - } - } - - /** Insure that the UI component is not stale, refresh if needed */ - public static void forceRefreshIfNeeded(TreeParent element) { - Node curNode = null; - - boolean doRefresh = false; - - try { - if (element instanceof SingleJcrNodeElem) { - curNode = ((SingleJcrNodeElem) element).getNode(); - } else if (element instanceof WorkspaceElem) { - curNode = ((WorkspaceElem) element).getRootNode(); - } - - if (curNode != null && element.getChildren().length != curNode.getNodes().getSize()) - doRefresh = true; - else if (element instanceof RepositoryElem) { - RepositoryElem rn = (RepositoryElem) element; - if (rn.isConnected()) { - String[] wkpNames = rn.getAccessibleWorkspaceNames(); - if (element.getChildren().length != wkpNames.length) - doRefresh = true; - } - } else if (element instanceof RepositoriesElem) { - doRefresh = true; - // Always force refresh for RepositoriesElem : the condition - // below does not take remote repository into account and it is - // not trivial to do so. - - // RepositoriesElem rn = (RepositoriesElem) element; - // if (element.getChildren().length != - // rn.getRepositoryRegister() - // .getRepositories().size()) - // doRefresh = true; - } - if (doRefresh) { - element.clearChildren(); - element.getChildren(); - } - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error while synchronising the UI with the JCR repository", re); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrDClickListener.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrDClickListener.java deleted file mode 100644 index 1707681b4..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrDClickListener.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import javax.jcr.Node; - -import org.argeo.cms.ui.jcr.model.RepositoryElem; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TreeViewer; - -/** Centralizes the management of double click on a NodeTreeViewer */ -public class JcrDClickListener implements IDoubleClickListener { - // private final static Log log = LogFactory - // .getLog(GenericNodeDoubleClickListener.class); - - private TreeViewer nodeViewer; - - // private JcrFileProvider jfp; - // private FileHandler fileHandler; - - public JcrDClickListener(TreeViewer nodeViewer) { - this.nodeViewer = nodeViewer; - // jfp = new JcrFileProvider(); - // Commented out. see https://www.argeo.org/bugzilla/show_bug.cgi?id=188 - // fileHandler = null; - // fileHandler = new FileHandler(jfp); - } - - public void doubleClick(DoubleClickEvent event) { - if (event.getSelection() == null || event.getSelection().isEmpty()) - return; - Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement(); - if (obj instanceof RepositoryElem) { - RepositoryElem rpNode = (RepositoryElem) obj; - if (rpNode.isConnected()) { - rpNode.logout(); - } else { - rpNode.login(); - } - nodeViewer.refresh(obj); - } else if (obj instanceof WorkspaceElem) { - WorkspaceElem wn = (WorkspaceElem) obj; - if (wn.isConnected()) - wn.logout(); - else - wn.login(); - nodeViewer.refresh(obj); - } else if (obj instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; - Node node = sjn.getNode(); - openNode(node); - } - } - - protected void openNode(Node node) { - // TODO implement generic behaviour - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrImages.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrImages.java deleted file mode 100644 index d1d1e31ef..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrImages.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import org.argeo.cms.ui.theme.CmsImages; -import org.eclipse.swt.graphics.Image; - -/** Shared icons. */ -public class JcrImages { - public final static Image NODE = CmsImages.createIcon("node.gif"); - public final static Image FOLDER = CmsImages.createIcon("folder.gif"); - public final static Image FILE = CmsImages.createIcon("file.gif"); - public final static Image BINARY = CmsImages.createIcon("binary.png"); - public final static Image HOME = CmsImages.createIcon("person-logged-in.png"); - public final static Image SORT = CmsImages.createIcon("sort.gif"); - public final static Image REMOVE = CmsImages.createIcon("remove.gif"); - - public final static Image REPOSITORIES = CmsImages.createIcon("repositories.gif"); - public final static Image REPOSITORY_DISCONNECTED = CmsImages.createIcon("repository_disconnected.gif"); - public final static Image REPOSITORY_CONNECTED = CmsImages.createIcon("repository_connected.gif"); - public final static Image REMOTE_DISCONNECTED = CmsImages.createIcon("remote_disconnected.gif"); - public final static Image REMOTE_CONNECTED = CmsImages.createIcon("remote_connected.gif"); - public final static Image WORKSPACE_DISCONNECTED = CmsImages.createIcon("workspace_disconnected.png"); - public final static Image WORKSPACE_CONNECTED = CmsImages.createIcon("workspace_connected.png"); - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrTreeContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrTreeContentProvider.java deleted file mode 100644 index cc8479f78..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/JcrTreeContentProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.jcr.util.JcrItemsComparator; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Implementation of the {@code ITreeContentProvider} in order to display a - * single JCR node and its children in a tree like structure - */ -public class JcrTreeContentProvider implements ITreeContentProvider { - private static final long serialVersionUID = -2128326504754297297L; - // private Node rootNode; - private JcrItemsComparator itemComparator = new JcrItemsComparator(); - - /** - * Sends back the first level of the Tree. input element must be a single node - * object - */ - public Object[] getElements(Object inputElement) { - Node rootNode = (Node) inputElement; - return childrenNodes(rootNode); - } - - public Object[] getChildren(Object parentElement) { - return childrenNodes((Node) parentElement); - } - - public Object getParent(Object element) { - try { - Node node = (Node) element; - if (!node.getPath().equals("/")) - return node.getParent(); - else - return null; - } catch (RepositoryException e) { - return null; - } - } - - public boolean hasChildren(Object element) { - try { - return ((Node) element).hasNodes(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check children existence on " + element, e); - } - } - - protected Object[] childrenNodes(Node parentNode) { - try { - List children = new ArrayList(); - NodeIterator nit = parentNode.getNodes(); - while (nit.hasNext()) { - Node node = nit.nextNode(); -// if (node.getName().startsWith("rep:") || node.getName().startsWith("jcr:") -// || node.getName().startsWith("nt:")) -// continue nodes; - children.add(node); - } - Node[] arr = children.toArray(new Node[0]); - Arrays.sort(arr, itemComparator); - return arr; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot list children of " + parentNode, e); - } - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java deleted file mode 100644 index 0625cc872..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.security.Keyring; -import org.argeo.cms.ui.jcr.model.RepositoriesElem; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ux.widgets.TreeParent; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** - * Implementation of the {@code ITreeContentProvider} to display multiple - * repository environment in a tree like structure - */ -public class NodeContentProvider implements ITreeContentProvider { - private static final long serialVersionUID = -4083809398848374403L; - final private RepositoryRegister repositoryRegister; - final private RepositoryFactory repositoryFactory; - - // Current user session on the default workspace of the argeo Node - final private Session userSession; - final private Keyring keyring; - private boolean sortChildren; - - // Reference for cleaning - private SingleJcrNodeElem homeNode = null; - private RepositoriesElem repositoriesNode = null; - - // Utils - private TreeBrowserComparator itemComparator = new TreeBrowserComparator(); - - public NodeContentProvider(Session userSession, Keyring keyring, - RepositoryRegister repositoryRegister, - RepositoryFactory repositoryFactory, Boolean sortChildren) { - this.userSession = userSession; - this.keyring = keyring; - this.repositoryRegister = repositoryRegister; - this.repositoryFactory = repositoryFactory; - this.sortChildren = sortChildren; - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (newInput == null)// dispose - return; - - if (userSession != null) { - Node userHome = CmsJcrUtils.getUserHome(userSession); - if (userHome != null) { - // TODO : find a way to dynamically get alias for the node - if (homeNode != null) - homeNode.dispose(); - homeNode = new SingleJcrNodeElem(null, userHome, - userSession.getUserID(), CmsConstants.EGO_REPOSITORY); - } - } - if (repositoryRegister != null) { - if (repositoriesNode != null) - repositoriesNode.dispose(); - repositoriesNode = new RepositoriesElem("Repositories", - repositoryRegister, repositoryFactory, null, userSession, - keyring); - } - } - - /** - * Sends back the first level of the Tree. Independent from inputElement - * that can be null - */ - public Object[] getElements(Object inputElement) { - List objs = new ArrayList(); - if (homeNode != null) - objs.add(homeNode); - if (repositoriesNode != null) - objs.add(repositoriesNode); - return objs.toArray(); - } - - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof TreeParent) { - if (sortChildren) { - Object[] tmpArr = ((TreeParent) parentElement).getChildren(); - if (tmpArr == null) - return new Object[0]; - TreeParent[] arr = new TreeParent[tmpArr.length]; - for (int i = 0; i < tmpArr.length; i++) - arr[i] = (TreeParent) tmpArr[i]; - Arrays.sort(arr, itemComparator); - return arr; - } else - return ((TreeParent) parentElement).getChildren(); - } else - return new Object[0]; - } - - /** - * Sets whether the content provider should order the children nodes or not. - * It is user duty to call a full refresh of the tree after changing this - * parameter. - */ - public void setSortChildren(boolean sortChildren) { - this.sortChildren = sortChildren; - } - - public Object getParent(Object element) { - if (element instanceof TreeParent) { - return ((TreeParent) element).getParent(); - } else - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof RepositoriesElem) { - RepositoryRegister rr = ((RepositoriesElem) element) - .getRepositoryRegister(); - return rr.getRepositories().size() > 0; - } else if (element instanceof TreeParent) { - TreeParent tp = (TreeParent) element; - return tp.hasChildren(); - } - return false; - } - - public void dispose() { - if (homeNode != null) - homeNode.dispose(); - if (repositoriesNode != null) { - // logs out open sessions - // see https://bugzilla.argeo.org/show_bug.cgi?id=23 - repositoriesNode.dispose(); - } - } - - /** - * Specific comparator for this view. See specification here: - * https://www.argeo.org/bugzilla/show_bug.cgi?id=139 - */ - private class TreeBrowserComparator implements Comparator { - - public int category(TreeParent element) { - if (element instanceof SingleJcrNodeElem) { - Node node = ((SingleJcrNodeElem) element).getNode(); - try { - if (node.isNodeType(NodeType.NT_FOLDER)) - return 5; - } catch (RepositoryException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return 10; - } - - public int compare(TreeParent o1, TreeParent o2) { - int cat1 = category(o1); - int cat2 = category(o2); - - if (cat1 != cat2) { - return cat1 - cat2; - } - return o1.getName().compareTo(o2.getName()); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeLabelProvider.java deleted file mode 100644 index a5751c083..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/NodeLabelProvider.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import javax.jcr.NamespaceException; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.ui.jcr.model.RemoteRepositoryElem; -import org.argeo.cms.ui.jcr.model.RepositoriesElem; -import org.argeo.cms.ui.jcr.model.RepositoryElem; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** Provides reasonable defaults for know JCR types. */ -public class NodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -3662051696443321843L; - - private final static CmsLog log = CmsLog.getLog(NodeLabelProvider.class); - - public String getText(Object element) { - try { - if (element instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; - return getText(sjn.getNode()); - } else if (element instanceof Node) { - return getText((Node) element); - } else - return super.getText(element); - } catch (RepositoryException e) { - throw new EclipseUiException("Unexpected JCR error while getting node name."); - } - } - - protected String getText(Node node) throws RepositoryException { - String label = node.getName(); - StringBuffer mixins = new StringBuffer(""); - for (NodeType type : node.getMixinNodeTypes()) - mixins.append(' ').append(type.getName()); - - return label + " [" + node.getPrimaryNodeType().getName() + mixins + "]"; - } - - @Override - public Image getImage(Object element) { - if (element instanceof RemoteRepositoryElem) { - if (((RemoteRepositoryElem) element).isConnected()) - return JcrImages.REMOTE_CONNECTED; - else - return JcrImages.REMOTE_DISCONNECTED; - } else if (element instanceof RepositoryElem) { - if (((RepositoryElem) element).isConnected()) - return JcrImages.REPOSITORY_CONNECTED; - else - return JcrImages.REPOSITORY_DISCONNECTED; - } else if (element instanceof WorkspaceElem) { - if (((WorkspaceElem) element).isConnected()) - return JcrImages.WORKSPACE_CONNECTED; - else - return JcrImages.WORKSPACE_DISCONNECTED; - } else if (element instanceof RepositoriesElem) { - return JcrImages.REPOSITORIES; - } else if (element instanceof SingleJcrNodeElem) { - Node nodeElem = ((SingleJcrNodeElem) element).getNode(); - return getImage(nodeElem); - - // if (element instanceof Node) { - // return getImage((Node) element); - // } else if (element instanceof WrappedNode) { - // return getImage(((WrappedNode) element).getNode()); - // } else if (element instanceof NodesWrapper) { - // return getImage(((NodesWrapper) element).getNode()); - // } - } - // try { - // return super.getImage(); - // } catch (RepositoryException e) { - // return null; - // } - return super.getImage(element); - } - - protected Image getImage(Node node) { - try { - if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) - return JcrImages.FILE; - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) - return JcrImages.FOLDER; - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_RESOURCE)) - return JcrImages.BINARY; - try { - // TODO check workspace type? - if (node.getDepth() == 1 && node.hasProperty(Property.JCR_ID)) - return JcrImages.HOME; - - // optimizes -// if (node.hasProperty(LdapAttrs.uid.property()) && node.isNodeType(NodeTypes.NODE_USER_HOME)) -// return JcrImages.HOME; - } catch (NamespaceException e) { - // node namespace is not registered in this repo - } - return JcrImages.NODE; - } catch (RepositoryException e) { - log.warn("Error while retrieving type for " + node + " in order to display corresponding image"); - e.printStackTrace(); - return null; - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/OsgiRepositoryRegister.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/OsgiRepositoryRegister.java deleted file mode 100644 index 444350aeb..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/OsgiRepositoryRegister.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; -import org.osgi.util.tracker.ServiceTracker; - -public class OsgiRepositoryRegister extends DefaultRepositoryRegister { - private final static BundleContext bc = FrameworkUtil.getBundle(OsgiRepositoryRegister.class).getBundleContext(); - private final ServiceTracker repositoryTracker; - - public OsgiRepositoryRegister() { - repositoryTracker = new ServiceTracker(bc, Repository.class, null) { - - @Override - public Repository addingService(ServiceReference reference) { - - Repository repository = super.addingService(reference); - Map props = new HashMap<>(); - for (String key : reference.getPropertyKeys()) { - props.put(key, reference.getProperty(key)); - } - register(repository, props); - return repository; - } - - @Override - public void removedService(ServiceReference reference, Repository service) { - Map props = new HashMap<>(); - for (String key : reference.getPropertyKeys()) { - props.put(key, reference.getProperty(key)); - } - unregister(service, props); - super.removedService(reference, service); - } - - }; - } - - public void init() { - repositoryTracker.open(); - } - - public void destroy() { - repositoryTracker.close(); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertiesContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertiesContentProvider.java deleted file mode 100644 index fd544bbd8..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertiesContentProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.Set; -import java.util.TreeSet; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.jcr.util.JcrItemsComparator; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** Simple content provider that displays all properties of a given Node */ -public class PropertiesContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 5227554668841613078L; - private JcrItemsComparator itemComparator = new JcrItemsComparator(); - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public Object[] getElements(Object inputElement) { - try { - if (inputElement instanceof Node) { - Set props = new TreeSet(itemComparator); - PropertyIterator pit = ((Node) inputElement).getProperties(); - while (pit.hasNext()) - props.add(pit.nextProperty()); - return props.toArray(); - } - return new Object[] {}; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get element for " - + inputElement, e); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertyLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertyLabelProvider.java deleted file mode 100644 index 37b90f7ee..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/PropertyLabelProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.cms.ui.CmsUiConstants; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ViewerCell; - -/** Default basic label provider for a given JCR Node's properties */ -public class PropertyLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -5405794508731390147L; - - // To be able to change column order easily - public static final int COLUMN_PROPERTY = 0; - public static final int COLUMN_VALUE = 1; - public static final int COLUMN_TYPE = 2; - public static final int COLUMN_ATTRIBUTES = 3; - - // Utils - protected DateFormat timeFormatter = new SimpleDateFormat(CmsUiConstants.DATE_TIME_FORMAT); - - public void update(ViewerCell cell) { - Object element = cell.getElement(); - cell.setText(getColumnText(element, cell.getColumnIndex())); - } - - public String getColumnText(Object element, int columnIndex) { - try { - if (element instanceof Property) { - Property prop = (Property) element; - if (prop.isMultiple()) { - switch (columnIndex) { - case COLUMN_PROPERTY: - return prop.getName(); - case COLUMN_VALUE: - // Corresponding values are listed on children - return ""; - case COLUMN_TYPE: - return JcrBrowserUtils.getPropertyTypeAsString(prop); - case COLUMN_ATTRIBUTES: - return JcrUtils.getPropertyDefinitionAsString(prop); - } - } else { - switch (columnIndex) { - case COLUMN_PROPERTY: - return prop.getName(); - case COLUMN_VALUE: - return formatValueAsString(prop.getValue()); - case COLUMN_TYPE: - return JcrBrowserUtils.getPropertyTypeAsString(prop); - case COLUMN_ATTRIBUTES: - return JcrUtils.getPropertyDefinitionAsString(prop); - } - } - } else if (element instanceof Value) { - Value val = (Value) element; - switch (columnIndex) { - case COLUMN_PROPERTY: - // Nothing to show - return ""; - case COLUMN_VALUE: - return formatValueAsString(val); - case COLUMN_TYPE: - // listed on the parent - return ""; - case COLUMN_ATTRIBUTES: - // Corresponding attributes are listed on the parent - return ""; - } - } - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot retrieve prop value on " + element, re); - } - return null; - } - - private String formatValueAsString(Value value) { - // TODO enhance this method - try { - String strValue; - - if (value.getType() == PropertyType.BINARY) - strValue = ""; - else if (value.getType() == PropertyType.DATE) - strValue = timeFormatter.format(value.getDate().getTime()); - else - strValue = value.getString(); - return strValue; - } catch (RepositoryException e) { - throw new EclipseUiException("unexpected error while formatting value", e); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/RepositoryRegister.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/RepositoryRegister.java deleted file mode 100644 index 802c75619..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/RepositoryRegister.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; - -/** Allows to register repositories by name. */ -public interface RepositoryRegister extends RepositoryFactory { - /** - * The registered {@link Repository} as a read-only map. Note that this - * method should be called for each access in order to be sure to be up to - * date in case repositories have registered/unregistered - */ - public Map getRepositories(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/VersionLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/VersionLabelProvider.java deleted file mode 100644 index 37dfe2b8f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/VersionLabelProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.argeo.cms.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; - -/** - * Simple wrapping of the ColumnLabelProvider class to provide text display in - * order to build a tree for version. The getText() method does not assume that - * {@link Version} extends {@link Node} class to respect JCR 2.0 specification - * - */ -public class VersionLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = 5270739851193688238L; - - public String getText(Object element) { - try { - if (element instanceof Version) { - Version version = (Version) element; - return version.getName(); - } else if (element instanceof Node) { - return ((Node) element).getName(); - } - } catch (RepositoryException re) { - throw new EclipseUiException( - "Unexpected error while getting element name", re); - } - return super.getText(element); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java deleted file mode 100644 index d33b33f63..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import javax.jcr.Repository; - -import org.argeo.cms.ux.widgets.TreeParent; - -/** Wrap a MaintainedRepository */ -public class MaintainedRepositoryElem extends RepositoryElem { - - public MaintainedRepositoryElem(String alias, Repository repository, TreeParent parent) { - super(alias, repository, parent); - // if (!(repository instanceof MaintainedRepository)) { - // throw new ArgeoException("Repository " + alias - // + " is not a maintained repository"); - // } - } - - // protected MaintainedRepository getMaintainedRepository() { - // return (MaintainedRepository) getRepository(); - // } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java deleted file mode 100644 index 908d1b135..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import java.util.Arrays; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.argeo.cms.ArgeoNames; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.security.Keyring; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; - -/** Root of a remote repository */ -public class RemoteRepositoryElem extends RepositoryElem { - private final Keyring keyring; - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - private final Session userSession; - private final String remoteNodePath; - - private final RepositoryFactory repositoryFactory; - private final String uri; - - public RemoteRepositoryElem(String alias, RepositoryFactory repositoryFactory, String uri, TreeParent parent, - Session userSession, Keyring keyring, String remoteNodePath) { - super(alias, null, parent); - this.repositoryFactory = repositoryFactory; - this.uri = uri; - this.keyring = keyring; - this.userSession = userSession; - this.remoteNodePath = remoteNodePath; - } - - @Override - protected Session repositoryLogin(String workspaceName) throws RepositoryException { - Node remoteRepository = userSession.getNode(remoteNodePath); - String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID).getString(); - if (userID.trim().equals("")) { - return getRepository().login(workspaceName); - } else { - String pwdPath = remoteRepository.getPath() + '/' + ArgeoNames.ARGEO_PASSWORD; - char[] password = keyring.getAsChars(pwdPath); - try { - SimpleCredentials credentials = new SimpleCredentials(userID, password); - return getRepository().login(credentials, workspaceName); - } finally { - Arrays.fill(password, 0, password.length, ' '); - } - } - } - - @Override - public Repository getRepository() { - if (repository == null) - repository = CmsJcrUtils.getRepositoryByUri(repositoryFactory, uri); - return super.getRepository(); - } - - public void remove() { - try { - Node remoteNode = userSession.getNode(remoteNodePath); - remoteNode.remove(); - remoteNode.getSession().save(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot remove " + remoteNodePath, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java deleted file mode 100644 index 8c40f8b37..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.argeo.cms.ArgeoNames; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.security.Keyring; -import org.argeo.cms.ui.jcr.RepositoryRegister; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; - -/** - * UI Tree component that implements the Argeo abstraction of a - * {@link RepositoryFactory} that enable a user to "mount" various repositories - * in a single Tree like View. It is usually meant to be at the root of the UI - * Tree and thus {@link #getParent()} method will return null. - * - * The {@link RepositoryFactory} is injected at instantiation time and must be - * use get or register new {@link Repository} objects upon which a reference is - * kept here. - */ - -public class RepositoriesElem extends TreeParent implements ArgeoNames { - private final RepositoryRegister repositoryRegister; - private final RepositoryFactory repositoryFactory; - - /** - * A session of the logged in user on the default workspace of the node - * repository. - */ - private final Session userSession; - private final Keyring keyring; - - public RepositoriesElem(String name, RepositoryRegister repositoryRegister, RepositoryFactory repositoryFactory, - TreeParent parent, Session userSession, Keyring keyring) { - super(name); - this.repositoryRegister = repositoryRegister; - this.repositoryFactory = repositoryFactory; - this.userSession = userSession; - this.keyring = keyring; - } - - /** - * Override normal behavior to initialize the various repositories only at - * request time - */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - Map refRepos = repositoryRegister.getRepositories(); - for (String name : refRepos.keySet()) { - Repository repository = refRepos.get(name); - // if (repository instanceof MaintainedRepository) - // super.addChild(new MaintainedRepositoryElem(name, - // repository, this)); - // else - super.addChild(new RepositoryElem(name, repository, this)); - } - - // remote - if (keyring != null) { - try { - addRemoteRepositories(keyring); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot browse remote repositories", e); - } - } - return super.getChildren(); - } - } - - protected void addRemoteRepositories(Keyring jcrKeyring) throws RepositoryException { - Node userHome = CmsJcrUtils.getUserHome(userSession); - if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) { - NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes(); - while (it.hasNext()) { - Node remoteNode = it.nextNode(); - String uri = remoteNode.getProperty(ARGEO_URI).getString(); - try { - RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem(remoteNode.getName(), - repositoryFactory, uri, this, userSession, jcrKeyring, remoteNode.getPath()); - super.addChild(remoteRepositoryNode); - } catch (Exception e) { - ErrorFeedback.show("Cannot add remote repository " + remoteNode, e); - } - } - } - } - - public void registerNewRepository(String alias, Repository repository) { - // TODO: implement this - // Create a new RepositoryNode Object - // add it - // super.addChild(new RepositoriesNode(...)); - } - - /** Returns the {@link RepositoryRegister} wrapped by this object. */ - public RepositoryRegister getRepositoryRegister() { - return repositoryRegister; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java deleted file mode 100644 index 296c36922..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.JcrUtils; - -/** - * UI Tree component that wraps a JCR {@link Repository}. It also keeps a - * reference to its parent Tree Ui component; typically the unique - * {@link RepositoriesElem} object of the current view to enable bi-directionnal - * browsing in the tree. - */ - -public class RepositoryElem extends TreeParent { - private String alias; - protected Repository repository; - private Session defaultSession = null; - - /** Create a new repository with distinct name and alias */ - public RepositoryElem(String alias, Repository repository, TreeParent parent) { - super(alias); - this.repository = repository; - setParent(parent); - this.alias = alias; - } - - public void login() { - try { - defaultSession = repositoryLogin(CmsConstants.SYS_WORKSPACE); - String[] wkpNames = defaultSession.getWorkspace().getAccessibleWorkspaceNames(); - for (String wkpName : wkpNames) { - if (wkpName.equals(defaultSession.getWorkspace().getName())) - addChild(new WorkspaceElem(this, wkpName, defaultSession)); - else - addChild(new WorkspaceElem(this, wkpName)); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot connect to repository " + alias, e); - } - } - - public synchronized void logout() { - for (Object child : getChildren()) { - if (child instanceof WorkspaceElem) - ((WorkspaceElem) child).logout(); - } - clearChildren(); - JcrUtils.logoutQuietly(defaultSession); - defaultSession = null; - } - - /** - * Actual call to the {@link Repository#login(javax.jcr.Credentials, String)} - * method. To be overridden. - */ - protected Session repositoryLogin(String workspaceName) throws RepositoryException { - return repository.login(workspaceName); - } - - public String[] getAccessibleWorkspaceNames() { - try { - return defaultSession.getWorkspace().getAccessibleWorkspaceNames(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot retrieve workspace names", e); - } - } - - public void createWorkspace(String workspaceName) { - if (!isConnected()) - login(); - try { - defaultSession.getWorkspace().createWorkspace(workspaceName); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot create workspace", e); - } - } - - /** returns the {@link Repository} referenced by the current UI Node */ - public Repository getRepository() { - return repository; - } - - public String getAlias() { - return alias; - } - - public Boolean isConnected() { - if (defaultSession != null && defaultSession.isLive()) - return true; - else - return false; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java deleted file mode 100644 index a2584a5e8..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Workspace; - -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; - -/** - * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a - * reference to its parent node that can either be a {@link WorkspaceElem}, a - * {@link SingleJcrNodeElem} or null if the node is "mounted" as the root of the - * UI tree. - */ -public class SingleJcrNodeElem extends TreeParent { - - private final Node node; - private String alias = null; - - /** Creates a new UiNode in the UI Tree */ - public SingleJcrNodeElem(TreeParent parent, Node node, String name) { - super(name); - setParent(parent); - this.node = node; - } - - /** - * Creates a new UiNode in the UI Tree, keeping a reference to the alias of - * the corresponding repository in the current UI environment. It is useful - * to be able to mount nodes as roots of the UI tree. - */ - public SingleJcrNodeElem(TreeParent parent, Node node, String name, String alias) { - super(name); - setParent(parent); - this.node = node; - this.alias = alias; - } - - /** Returns the node wrapped by the current UI object */ - public Node getNode() { - return node; - } - - protected String getRepositoryAlias() { - return alias; - } - - /** - * Overrides normal behaviour to initialise children only when first - * requested - */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - try { - NodeIterator ni = node.getNodes(); - while (ni.hasNext()) { - Node curNode = ni.nextNode(); - addChild(new SingleJcrNodeElem(this, curNode, curNode.getName())); - } - return super.getChildren(); - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot initialize SingleJcrNode children", re); - } - } - } - - @Override - public boolean hasChildren() { - try { - if (node.getSession().isLive()) - return node.hasNodes(); - else - return false; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot check children node existence", re); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java deleted file mode 100644 index 2d786669f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.argeo.cms.ui.jcr.model; - -import javax.jcr.AccessDeniedException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -// import javax.jcr.Workspace; -import javax.jcr.Workspace; - -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.JcrUtils; - -/** - * UI Tree component. Wraps the root node of a JCR {@link Workspace}. It also - * keeps a reference to its parent {@link RepositoryElem}, to be able to - * retrieve alias of the current used repository - */ -public class WorkspaceElem extends TreeParent { - private Session session = null; - - public WorkspaceElem(RepositoryElem parent, String name) { - this(parent, name, null); - } - - public WorkspaceElem(RepositoryElem parent, String name, Session session) { - super(name); - this.session = session; - setParent(parent); - } - - public synchronized Session getSession() { - return session; - } - - public synchronized Node getRootNode() { - try { - if (session != null) - return session.getRootNode(); - else - return null; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get root node of workspace " + getName(), e); - } - } - - public synchronized void login() { - try { - session = ((RepositoryElem) getParent()).repositoryLogin(getName()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot connect to repository " + getName(), e); - } - } - - public Boolean isConnected() { - if (session != null && session.isLive()) - return true; - else - return false; - } - - @Override - public synchronized void dispose() { - logout(); - super.dispose(); - } - - /** Logouts the session, does not nothing if there is no live session. */ - public synchronized void logout() { - clearChildren(); - JcrUtils.logoutQuietly(session); - session = null; - } - - @Override - public synchronized boolean hasChildren() { - try { - if (isConnected()) - try { - return session.getRootNode().hasNodes(); - } catch (AccessDeniedException e) { - // current user may not have access to the root node - return false; - } - else - return false; - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error while checking children node existence", re); - } - } - - /** Override normal behaviour to initialize display of the workspace */ - @Override - public synchronized Object[] getChildren() { - if (isLoaded()) { - return super.getChildren(); - } else { - // initialize current object - try { - Node rootNode; - if (session == null) - return null; - else - rootNode = session.getRootNode(); - NodeIterator ni = rootNode.getNodes(); - while (ni.hasNext()) { - Node node = ni.nextNode(); - addChild(new SingleJcrNodeElem(this, node, node.getName())); - } - return super.getChildren(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot initialize WorkspaceNode UI object." + getName(), e); - } - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/package-info.java deleted file mode 100644 index 8f5474449..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/model/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Model for SWT/JFace JCR components. */ -package org.argeo.cms.ui.jcr.model; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/package-info.java deleted file mode 100644 index 26ae330b5..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/jcr/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** SWT/JFace JCR components. */ -package org.argeo.cms.ui.jcr; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/package-info.java deleted file mode 100644 index 82fdee796..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** SWT/JFace components for Argeo CMS. */ -package org.argeo.cms.ui; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsLink.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsLink.java deleted file mode 100644 index e91f9ba48..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsLink.java +++ /dev/null @@ -1,282 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.CmsStyle; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.jcr.JcrException; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.service.ResourceManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.osgi.framework.BundleContext; - -/** A link to an internal or external location. */ -public class CmsLink implements CmsUiProvider { - private final static CmsLog log = CmsLog.getLog(CmsLink.class); - private BundleContext bundleContext; - - private String label; - private String style; - private String target; - private String image; - private boolean openNew = false; - private MouseListener mouseListener; - - private int horizontalAlignment = SWT.CENTER; - private int verticalAlignment = SWT.CENTER; - - private String loggedInLabel = null; - private String loggedInTarget = null; - - // internal - // private Boolean isUrl = false; - private Integer imageWidth, imageHeight; - - public CmsLink() { - super(); - } - - public CmsLink(String label, String target) { - this(label, target, (String) null); - } - - public CmsLink(String label, String target, CmsStyle style) { - this(label, target, style != null ? style.style() : null); - } - - public CmsLink(String label, String target, String style) { - super(); - this.label = label; - this.target = target; - this.style = style; - init(); - } - - public void init() { - if (image != null) { - ImageData image = loadImage(); - if (imageHeight == null && imageWidth == null) { - imageWidth = image.width; - imageHeight = image.height; - } else if (imageHeight == null) { - imageHeight = (imageWidth * image.height) / image.width; - } else if (imageWidth == null) { - imageWidth = (imageHeight * image.width) / image.height; - } - } - } - - /** @return {@link Composite} with a single {@link Label} child. */ - @Override - public Control createUi(final Composite parent, Node context) { -// if (image != null && (imageWidth == null || imageHeight == null)) { -// throw new CmsException("Image is not properly configured." -// + " Make sure bundleContext property is set and init() method has been called."); -// } - - Composite comp = new Composite(parent, SWT.NONE); - comp.setLayout(CmsSwtUtils.noSpaceGridLayout()); - - Label link = new Label(comp, SWT.NONE); - CmsSwtUtils.markup(link); - GridData layoutData = new GridData(horizontalAlignment, verticalAlignment, false, false); - if (image != null) { - if (imageHeight != null) - layoutData.heightHint = imageHeight; - if (label == null) - if (imageWidth != null) - layoutData.widthHint = imageWidth; - } - - link.setLayoutData(layoutData); - CmsSwtUtils.style(comp, style != null ? style : getDefaultStyle()); - CmsSwtUtils.style(link, style != null ? style : getDefaultStyle()); - - // label - StringBuilder labelText = new StringBuilder(); - if (loggedInTarget != null && isLoggedIn()) { - labelText.append(""); - } else if (target != null) { - labelText.append(""); - } - if (image != null) { - registerImageIfNeeded(); - String imageLocation = RWT.getResourceManager().getLocation(image); - labelText.append(""); - - } - - if (loggedInLabel != null && isLoggedIn()) { - labelText.append(' ').append(loggedInLabel); - } else if (label != null) { - labelText.append(' ').append(label); - } - - if ((loggedInTarget != null && isLoggedIn()) || target != null) - labelText.append(""); - - link.setText(labelText.toString()); - - if (mouseListener != null) - link.addMouseListener(mouseListener); - - return comp; - } - - private void registerImageIfNeeded() { - ResourceManager resourceManager = RWT.getResourceManager(); - if (!resourceManager.isRegistered(image)) { - URL res = getImageUrl(); - try (InputStream inputStream = res.openStream()) { - resourceManager.register(image, inputStream); - if (log.isTraceEnabled()) - log.trace("Registered image " + image); - } catch (IOException e) { - throw new RuntimeException("Cannot load image " + image, e); - } - } - } - - private ImageData loadImage() { - URL url = getImageUrl(); - ImageData result = null; - try (InputStream inputStream = url.openStream()) { - result = new ImageData(inputStream); - if (log.isTraceEnabled()) - log.trace("Loaded image " + image); - } catch (IOException e) { - throw new RuntimeException("Cannot load image " + image, e); - } - return result; - } - - private URL getImageUrl() { - URL url; - try { - // pure URL - url = new URL(image); - } catch (MalformedURLException e1) { - url = bundleContext.getBundle().getResource(image); - } - - if (url == null) - throw new IllegalStateException("No image " + image + " available."); - - return url; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public void setLabel(String label) { - this.label = label; - } - - public void setStyle(String style) { - this.style = style; - } - - /** @deprecated Use {@link #setStyle(String)} instead. */ - @Deprecated - public void setCustom(String custom) { - this.style = custom; - } - - public void setTarget(String target) { - this.target = target; - // try { - // new URL(target); - // isUrl = true; - // } catch (MalformedURLException e1) { - // isUrl = false; - // } - } - - public void setImage(String image) { - this.image = image; - } - - public void setLoggedInLabel(String loggedInLabel) { - this.loggedInLabel = loggedInLabel; - } - - public void setLoggedInTarget(String loggedInTarget) { - this.loggedInTarget = loggedInTarget; - } - - public void setMouseListener(MouseListener mouseListener) { - this.mouseListener = mouseListener; - } - - public void setvAlign(String vAlign) { - if ("bottom".equals(vAlign)) { - verticalAlignment = SWT.BOTTOM; - } else if ("top".equals(vAlign)) { - verticalAlignment = SWT.TOP; - } else if ("center".equals(vAlign)) { - verticalAlignment = SWT.CENTER; - } else { - throw new IllegalArgumentException( - "Unsupported vertical alignment " + vAlign + " (must be: top, bottom or center)"); - } - } - - protected boolean isLoggedIn() { - return !CurrentUser.isAnonymous(); - } - - public void setImageWidth(Integer imageWidth) { - this.imageWidth = imageWidth; - } - - public void setImageHeight(Integer imageHeight) { - this.imageHeight = imageHeight; - } - - public void setOpenNew(boolean openNew) { - this.openNew = openNew; - } - - protected String getDefaultStyle() { - return SimpleStyle.link.name(); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsPane.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsPane.java deleted file mode 100644 index fc0c82146..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsPane.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.argeo.cms.ui.util; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Composite; - -/** The main pane of a CMS display, with QA and support areas. */ -public class CmsPane { - - private Composite mainArea; - private Composite qaArea; - private Composite supportArea; - - public CmsPane(Composite parent, int style) { - parent.setLayout(CmsSwtUtils.noSpaceGridLayout()); - -// qaArea = new Composite(parent, SWT.NONE); -// qaArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); -// RowLayout qaLayout = new RowLayout(); -// qaLayout.spacing = 0; -// qaArea.setLayout(qaLayout); - - mainArea = new Composite(parent, SWT.NONE); - mainArea.setLayout(new GridLayout()); - mainArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - -// supportArea = new Composite(parent, SWT.NONE); -// supportArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); -// RowLayout supportLayout = new RowLayout(); -// supportLayout.spacing = 0; -// supportArea.setLayout(supportLayout); - } - - public Composite getMainArea() { - return mainArea; - } - - public Composite getQaArea() { - return qaArea; - } - - public Composite getSupportArea() { - return supportArea; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java deleted file mode 100644 index 3522f1b42..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.servlet.http.HttpServletRequest; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.api.cms.ux.CmsView; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiConstants; -import org.argeo.cms.ux.AbstractImageManager; -import org.argeo.cms.ux.CmsUxUtils; -import org.argeo.jcr.JcrUtils; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.service.ResourceManager; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.layout.RowData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Table; - -/** Static utilities for the CMS framework. */ -public class CmsUiUtils { - // private final static Log log = LogFactory.getLog(CmsUiUtils.class); - - /* - * CMS VIEW - */ - - /** - * The CMS view related to this display, or null if none is available from this - * call. - * - * @deprecated Use {@link CmsSwtUtils#getCmsView(Composite)} instead. - */ - @Deprecated - public static CmsView getCmsView() { -// return UiContext.getData(CmsView.class.getName()); - return CmsSwtUtils.getCmsView(Display.getCurrent().getActiveShell()); - } - - public static StringBuilder getServerBaseUrl(HttpServletRequest request) { - try { - URL url = new URL(request.getRequestURL().toString()); - StringBuilder buf = new StringBuilder(); - buf.append(url.getProtocol()).append("://").append(url.getHost()); - if (url.getPort() != -1) - buf.append(':').append(url.getPort()); - return buf; - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot extract server base URL from " + request.getRequestURL(), e); - } - } - - // - public static String getDataUrl(Node node, HttpServletRequest request) { - try { - StringBuilder buf = getServerBaseUrl(request); - buf.append(getDataPath(node)); - return new URL(buf.toString()).toString(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot build data URL for " + node, e); - } - } - - /** A path in the node repository */ - public static String getDataPath(Node node) { - return getDataPath(CmsConstants.EGO_REPOSITORY, node); - } - - public static String getDataPath(String cn, Node node) { - return CmsJcrUtils.getDataPath(cn, node); - } - - /** Clean reserved URL characters for use in HTTP links. */ - public static String getDataPathForUrl(Node node) { - return CmsSwtUtils.cleanPathForUrl(getDataPath(node)); - } - - /** @deprecated Use rowData16px() instead. GridData should not be reused. */ - @Deprecated - public static RowData ROW_DATA_16px = new RowData(16, 16); - - - - /* - * FORM LAYOUT - */ - - - - @Deprecated - public static void setItemHeight(Table table, int height) { - table.setData(CmsUiConstants.ITEM_HEIGHT, height); - } - - // - // JCR - // - public static Node getOrAddEmptyFile(Node parent, Enum child) throws RepositoryException { - if (has(parent, child)) - return child(parent, child); - return JcrUtils.copyBytesAsFile(parent, child.name(), new byte[0]); - } - - public static Node child(Node parent, Enum en) throws RepositoryException { - return parent.getNode(en.name()); - } - - public static Boolean has(Node parent, Enum en) throws RepositoryException { - return parent.hasNode(en.name()); - } - - public static Node getOrAdd(Node parent, Enum en) throws RepositoryException { - return getOrAdd(parent, en, null); - } - - public static Node getOrAdd(Node parent, Enum en, String primaryType) throws RepositoryException { - if (has(parent, en)) - return child(parent, en); - else if (primaryType == null) - return parent.addNode(en.name()); - else - return parent.addNode(en.name(), primaryType); - } - - // IMAGES - - public static String img(Node fileNode, String width, String height) { - return img(null, fileNode, width, height); - } - - public static String img(String serverBase, Node fileNode, String width, String height) { -// String src = (serverBase != null ? serverBase : "") + NodeUtils.getDataPath(fileNode); - String src; - src = (serverBase != null ? serverBase : "") + getDataPathForUrl(fileNode); - return CmsUxUtils.imgBuilder(src, width, height).append("/>").toString(); - } - - public static String noImg(Cms2DSize size) { - ResourceManager rm = RWT.getResourceManager(); - return CmsUxUtils.img(rm.getLocation(AbstractImageManager.NO_IMAGE), size); - } - - public static String noImg() { - return noImg(AbstractImageManager.NO_IMAGE_SIZE); - } - -// public static Image noImage(Cms2DSize size) { -// ResourceManager rm = RWT.getResourceManager(); -// InputStream in = null; -// try { -// in = rm.getRegisteredContent(AbstractImageManager.NO_IMAGE); -// ImageData id = new ImageData(in); -// ImageData scaled = id.scaledTo(size.getWidth(), size.getHeight()); -// Image image = new Image(Display.getCurrent(), scaled); -// return image; -// } finally { -// try { -// in.close(); -// } catch (IOException e) { -// // silent -// } -// } -// } - - /** Lorem ipsum text to be used during development. */ - public final static String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - + " Etiam eleifend hendrerit sem, ac ultricies massa ornare ac." - + " Cras aliquam sodales risus, vitae varius lacus molestie quis." - + " Vivamus consequat, leo id lacinia volutpat, eros diam efficitur urna, finibus interdum risus turpis at nisi." - + " Curabitur vulputate nulla quis scelerisque fringilla. Integer consectetur turpis id lobortis accumsan." - + " Pellentesque commodo turpis ac diam ultricies dignissim." - + " Curabitur sit amet dolor volutpat lacus aliquam ornare quis sed velit." - + " Integer varius quis est et tristique." - + " Suspendisse pharetra porttitor purus, eget condimentum magna." - + " Duis vitae turpis eros. Sed tincidunt lacinia rutrum." - + " Aliquam velit velit, rutrum ut augue sed, condimentum lacinia augue."; - - /** Singleton. */ - private CmsUiUtils() { - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/DefaultImageManager.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/DefaultImageManager.java deleted file mode 100644 index b431fc3c9..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/DefaultImageManager.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.argeo.cms.ui.util; - -import static javax.jcr.Node.JCR_CONTENT; -import static javax.jcr.Property.JCR_DATA; -import static javax.jcr.nodetype.NodeType.NT_FILE; -import static javax.jcr.nodetype.NodeType.NT_RESOURCE; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.cms.swt.AbstractSwtImageManager; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.rap.rwt.service.ResourceManager; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.widgets.Display; - -/** Manages only public images so far. */ -public class DefaultImageManager extends AbstractSwtImageManager { - private final static CmsLog log = CmsLog.getLog(DefaultImageManager.class); - - /** @return null if not available */ - @Override - public String getImageUrl(Node node) { - return CmsUiUtils.getDataPathForUrl(node); - } - - protected String getResourceName(Node node) { - try { - String workspace = node.getSession().getWorkspace().getName(); - if (node.hasNode(JCR_CONTENT)) - return workspace + '_' + node.getNode(JCR_CONTENT).getIdentifier(); - else - return workspace + '_' + node.getIdentifier(); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - public Binary getImageBinary(Node node) { - try { - if (node.isNodeType(NT_FILE)) { - return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary(); - } else { - return null; - } - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - public Image getSwtImage(Node node) { - InputStream inputStream = null; - Binary binary = getImageBinary(node); - if (binary == null) - return null; - try { - inputStream = binary.getStream(); - return new Image(Display.getCurrent(), inputStream); - } catch (RepositoryException e) { - throw new JcrException(e); - } finally { - IOUtils.closeQuietly(inputStream); - JcrUtils.closeQuietly(binary); - } - } - - @Override - public String uploadImage(Node context, Node parentNode, String fileName, InputStream in, String contentType) { - InputStream inputStream = null; - try { - String previousResourceName = null; - if (parentNode.hasNode(fileName)) { - Node node = parentNode.getNode(fileName); - previousResourceName = getResourceName(node); - if (node.hasNode(JCR_CONTENT)) { - node.getNode(JCR_CONTENT).remove(); - node.addNode(JCR_CONTENT, NT_RESOURCE); - } - } - - byte[] arr = IOUtils.toByteArray(in); - Node fileNode = JcrUtils.copyBytesAsFile(parentNode, fileName, arr); - inputStream = new ByteArrayInputStream(arr); - ImageData id = new ImageData(inputStream); - processNewImageFile(context, fileNode, id); - - String mime = contentType != null ? contentType : Files.probeContentType(Paths.get(fileName)); - if (mime != null) { - fileNode.getNode(JCR_CONTENT).setProperty(Property.JCR_MIMETYPE, mime); - } - fileNode.getSession().save(); - - // reset resource manager - ResourceManager resourceManager = RWT.getResourceManager(); - if (previousResourceName != null && resourceManager.isRegistered(previousResourceName)) { - resourceManager.unregister(previousResourceName); - if (log.isDebugEnabled()) - log.debug("Unregistered image " + previousResourceName); - } - return CmsUiUtils.getDataPath(fileNode); - } catch (IOException e) { - throw new RuntimeException("Cannot upload image " + fileName + " in " + parentNode, e); - } catch (RepositoryException e) { - throw new JcrException(e); - } finally { - IOUtils.closeQuietly(inputStream); - } - } - - /** Does nothing by default. */ - protected void processNewImageFile(Node context, Node fileNode, ImageData id) - throws RepositoryException, IOException { - } - - @Override - protected String noImg(Cms2DSize size) { - return CmsUiUtils.noImg(size); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/MenuLink.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/MenuLink.java deleted file mode 100644 index 284d2bd0c..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/MenuLink.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.argeo.cms.ui.util; - -import org.argeo.cms.swt.CmsStyles; - -/** - * Convenience class setting the custom style {@link CmsStyles#CMS_MENU_LINK} on - * a {@link CmsLink} when simple menus are used. - */ -public class MenuLink extends CmsLink { - public MenuLink() { - setCustom(CmsStyles.CMS_MENU_LINK); - } - - public MenuLink(String label, String target, String custom) { - super(label, target, custom); - } - - public MenuLink(String label, String target) { - super(label, target, CmsStyles.CMS_MENU_LINK); - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java deleted file mode 100644 index ab6a29f7d..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsStyles; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiProvider; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** A header in three parts */ -public class SimpleCmsHeader implements CmsUiProvider { - private List lead = new ArrayList(); - private List center = new ArrayList(); - private List end = new ArrayList(); - - private Boolean subPartsSameWidth = false; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - Composite header = new Composite(parent, SWT.NONE); - header.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_HEADER); - header.setBackgroundMode(SWT.INHERIT_DEFAULT); - header.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(3, false))); - - configurePart(context, header, lead); - configurePart(context, header, center); - configurePart(context, header, end); - return header; - } - - protected void configurePart(Node context, Composite parent, List partProviders) - throws RepositoryException { - final int style; - final String custom; - if (lead == partProviders) { - style = SWT.LEAD; - custom = CmsStyles.CMS_HEADER_LEAD; - } else if (center == partProviders) { - style = SWT.CENTER; - custom = CmsStyles.CMS_HEADER_CENTER; - } else if (end == partProviders) { - style = SWT.END; - custom = CmsStyles.CMS_HEADER_END; - } else { - throw new CmsException("Unsupported part providers " + partProviders); - } - - Composite part = new Composite(parent, SWT.NONE); - part.setData(RWT.CUSTOM_VARIANT, custom); - GridData gridData = new GridData(style, SWT.FILL, true, true); - part.setLayoutData(gridData); - part.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(partProviders.size(), subPartsSameWidth))); - for (CmsUiProvider uiProvider : partProviders) { - Control subPart = uiProvider.createUi(part, context); - subPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - } - } - - public void setLead(List lead) { - this.lead = lead; - } - - public void setCenter(List center) { - this.center = center; - } - - public void setEnd(List end) { - this.end = end; - } - - public void setSubPartsSameWidth(Boolean subPartsSameWidth) { - this.subPartsSameWidth = subPartsSameWidth; - } - - public List getLead() { - return lead; - } - - public List getCenter() { - return center; - } - - public List getEnd() { - return end; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java deleted file mode 100644 index c61a2fc9e..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.jcr.JcrUtils; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; - -public class SimpleDynamicPages implements CmsUiProvider { - - @Override - public Control createUi(Composite parent, Node context) - throws RepositoryException { - if (context == null) - throw new CmsException("Context cannot be null"); - parent.setLayout(new GridLayout(2, false)); - - // parent - if (!context.getPath().equals("/")) { - new CmsLink("..", context.getParent().getPath()).createUi(parent, - context); - new Label(parent, SWT.NONE).setText(context.getParent() - .getPrimaryNodeType().getName()); - } - - // context - Label contextL = new Label(parent, SWT.NONE); - contextL.setData(RWT.MARKUP_ENABLED, true); - contextL.setText("" + context.getName() + ""); - new Label(parent, SWT.NONE).setText(context.getPrimaryNodeType() - .getName()); - - // children - // Label childrenL = new Label(parent, SWT.NONE); - // childrenL.setData(RWT.MARKUP_ENABLED, true); - // childrenL.setText("Children:"); - // childrenL.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, - // false, 2, 1)); - - for (NodeIterator nIt = context.getNodes(); nIt.hasNext();) { - Node child = nIt.nextNode(); - new CmsLink(child.getName(), child.getPath()).createUi(parent, - context); - - new Label(parent, SWT.NONE).setText(child.getPrimaryNodeType() - .getName()); - } - - // properties - // Label propsL = new Label(parent, SWT.NONE); - // propsL.setData(RWT.MARKUP_ENABLED, true); - // propsL.setText("Properties:"); - // propsL.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false, - // 2, 1)); - for (PropertyIterator pIt = context.getProperties(); pIt.hasNext();) { - Property property = pIt.nextProperty(); - - Label label = new Label(parent, SWT.NONE); - label.setText(property.getName()); - label.setToolTipText(JcrUtils - .getPropertyDefinitionAsString(property)); - - new Label(parent, SWT.NONE).setText(getPropAsString(property)); - } - - return null; - } - - private String getPropAsString(Property property) - throws RepositoryException { - String result = ""; - DateFormat timeFormatter = new SimpleDateFormat(""); - if (property.isMultiple()) { - result = getMultiAsString(property, ", "); - } else { - Value value = property.getValue(); - if (value.getType() == PropertyType.BINARY) - result = ""; - else if (value.getType() == PropertyType.DATE) - result = timeFormatter.format(value.getDate().getTime()); - else - result = value.getString(); - } - return result; - } - - private String getMultiAsString(Property property, String separator) - throws RepositoryException { - if (separator == null) - separator = "; "; - Value[] values = property.getValues(); - StringBuilder builder = new StringBuilder(); - for (Value val : values) { - String currStr = val.getString(); - if (!"".equals(currStr.trim())) - builder.append(currStr).append(separator); - } - if (builder.lastIndexOf(separator) >= 0) - return builder.substring(0, builder.length() - separator.length()); - else - return builder.toString(); - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStaticPage.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStaticPage.java deleted file mode 100644 index 63e504b7a..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStaticPage.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.argeo.cms.ui.util; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsStyles; -import org.argeo.cms.ui.CmsUiProvider; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; - -public class SimpleStaticPage implements CmsUiProvider { - private String text; - - @Override - public Control createUi(Composite parent, Node context) - throws RepositoryException { - Label textC = new Label(parent, SWT.WRAP); - textC.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_STATIC_TEXT); - textC.setData(RWT.MARKUP_ENABLED, Boolean.TRUE); - textC.setText(text); - - return textC; - } - - public void setText(String text) { - this.text = text; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStyle.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStyle.java deleted file mode 100644 index b5fca2699..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SimpleStyle.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.ui.util; - -import org.argeo.api.cms.ux.CmsStyle; - -/** Simple styles used by the CMS UI utilities. */ -public enum SimpleStyle implements CmsStyle { - link; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java deleted file mode 100644 index 1e17dc930..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.apache.commons.io.IOUtils; -import org.argeo.cms.swt.CmsException; -import org.eclipse.rap.rwt.service.ResourceLoader; -import org.osgi.framework.Bundle; - -/** {@link ResourceLoader} caching stylesheets. */ -public class StyleSheetResourceLoader implements ResourceLoader { - private Bundle themeBundle; - private Map stylesheets = new LinkedHashMap(); - - public StyleSheetResourceLoader(Bundle themeBundle) { - this.themeBundle = themeBundle; - } - - @Override - public InputStream getResourceAsStream(String resourceName) throws IOException { - if (!stylesheets.containsKey(resourceName)) { - // TODO deal with other bundles - // Bundle bundle = bundleContext.getBundle(); - // String location = - // bundle.getLocation().substring("initial@reference:".length()); - // if (location.startsWith("file:")) { - // Path path = null; - // try { - // path = Paths.get(new URI(location)); - // } catch (URISyntaxException e) { - // e.printStackTrace(); - // } - // if (path != null) { - // Path resourcePath = path.resolve(resourceName); - // if (Files.exists(resourcePath)) - // return Files.newInputStream(resourcePath); - // } - // } - - URL res = themeBundle.getEntry(resourceName); - if (res == null) - throw new CmsException( - "Entry " + resourceName + " not found in bundle " + themeBundle.getSymbolicName()); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - IOUtils.copy(res.openStream(), out); - stylesheets.put(resourceName, new StyleSheet(out.toByteArray())); - } - return new ByteArrayInputStream(stylesheets.get(resourceName).getData()); - // return res.openStream(); - } - - private class StyleSheet { - private byte[] data; - - public StyleSheet(byte[] data) { - super(); - this.data = data; - } - - public byte[] getData() { - return data; - } - - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SystemNotifications.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SystemNotifications.java deleted file mode 100644 index 5a0078163..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/SystemNotifications.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.io.IOUtils; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsStyles; -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -/** Shell displaying system notifications such as exceptions */ -public class SystemNotifications extends Shell implements CmsStyles, - MouseListener { - private static final long serialVersionUID = -8129377525216022683L; - - private Control source; - - public SystemNotifications(Control source) { - super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU); - - this.source = source; - - // TODO UI - // setLocation(source.toDisplay(source.getSize().x - getSize().x, - // source.getSize().y)); - setLayout(new GridLayout()); - addMouseListener(this); - - addShellListener(new ShellAdapter() { - private static final long serialVersionUID = 5178980294808435833L; - - @Override - public void shellDeactivated(ShellEvent e) { - close(); - dispose(); - } - }); - - } - - public void notifyException(Throwable exception) { - Composite pane = this; - - Label lbl = new Label(pane, SWT.NONE); - lbl.setText(exception.getLocalizedMessage() - + (exception instanceof CmsException ? "" : "(" - + exception.getClass().getName() + ")") + "\n"); - lbl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - lbl.addMouseListener(this); - if (exception.getCause() != null) - appendCause(pane, exception.getCause()); - - StringBuilder mailToUrl = new StringBuilder("mailto:?"); - try { - mailToUrl.append("subject=").append( - URLEncoder.encode( - "Exception " - + new SimpleDateFormat("yyyy-MM-dd hh:mm") - .format(new Date()), "UTF-8") - .replace("+", "%20")); - - StringWriter sw = new StringWriter(); - exception.printStackTrace(new PrintWriter(sw)); - IOUtils.closeQuietly(sw); - - // see - // http://stackoverflow.com/questions/4737841/urlencoder-not-able-to-translate-space-character - String encoded = URLEncoder.encode(sw.toString(), "UTF-8").replace( - "+", "%20"); - mailToUrl.append("&body=").append(encoded); - } catch (UnsupportedEncodingException e) { - mailToUrl.append("&body=").append("Could not encode: ") - .append(e.getMessage()); - } - Label mailTo = new Label(pane, SWT.NONE); - CmsSwtUtils.markup(mailTo); - mailTo.setText("Send details"); - mailTo.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); - - pack(); - layout(); - - setLocation(source.toDisplay(source.getSize().x - getSize().x, - source.getSize().y - getSize().y)); - open(); - } - - private void appendCause(Composite parent, Throwable e) { - Label lbl = new Label(parent, SWT.NONE); - lbl.setText(" caused by: " + e.getLocalizedMessage() + " (" - + e.getClass().getName() + ")" + "\n"); - lbl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - lbl.addMouseListener(this); - if (e.getCause() != null) - appendCause(parent, e.getCause()); - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - } - - @Override - public void mouseDown(MouseEvent e) { - close(); - dispose(); - } - - @Override - public void mouseUp(MouseEvent e) { - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenu.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenu.java deleted file mode 100644 index 09aeff60f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenu.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.argeo.cms.ui.util; - -import javax.jcr.Node; - -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.auth.CmsLoginShell; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -/** The site-related user menu */ -public class UserMenu extends CmsLoginShell { - private final Control source; - private final Node context; - - public UserMenu(Control source, Node context) { - // FIXME pass CMS context - super(CmsUiUtils.getCmsView(), null); - this.context = context; - createUi(); - if (source == null) - throw new CmsException("Source control cannot be null."); - this.source = source; - open(); - } - - @Override - protected Shell createShell() { - return new Shell(Display.getCurrent(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - } - - @Override - public void open() { - Shell shell = getShell(); - shell.pack(); - shell.layout(); - shell.setLocation(source.toDisplay(source.getSize().x - shell.getSize().x, source.getSize().y)); - shell.addShellListener(new ShellAdapter() { - private static final long serialVersionUID = 5178980294808435833L; - - @Override - public void shellDeactivated(ShellEvent e) { - closeShell(); - } - }); - super.open(); - } - - protected Node getContext() { - return context; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenuLink.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenuLink.java deleted file mode 100644 index 317a7b55b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/UserMenuLink.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.argeo.cms.ui.util; - -import javax.jcr.Node; - -import org.argeo.cms.CmsMsg; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.swt.CmsStyles; -import org.argeo.cms.swt.auth.CmsLoginShell; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; - -/** Open the user menu when clicked */ -public class UserMenuLink extends MenuLink { - - public UserMenuLink() { - setCustom(CmsStyles.CMS_USER_MENU_LINK); - } - - @Override - public Control createUi(Composite parent, Node context) { - if (CurrentUser.isAnonymous()) - setLabel(CmsMsg.login.lead()); - else { - setLabel(CurrentUser.getDisplayName()); - } - Label link = (Label) ((Composite) super.createUi(parent, context)).getChildren()[0]; - link.addMouseListener(new UserMenuLinkController(context)); - return link.getParent(); - } - - protected CmsLoginShell createUserMenu(Control source, Node context) { - return new UserMenu(source.getParent(), context); - } - - private class UserMenuLinkController implements MouseListener, DisposeListener { - private static final long serialVersionUID = 3634864186295639792L; - - private CmsLoginShell userMenu = null; - private long lastDisposeTS = 0l; - - private final Node context; - - public UserMenuLinkController(Node context) { - this.context = context; - } - - // - // MOUSE LISTENER - // - @Override - public void mouseDown(MouseEvent e) { - if (e.button == 1) { - Control source = (Control) e.getSource(); - if (userMenu == null) { - long durationSinceLastDispose = System.currentTimeMillis() - lastDisposeTS; - // avoid to reopen the menu, if one has clicked gain - if (durationSinceLastDispose > 200) { - userMenu = createUserMenu(source, context); - userMenu.getShell().addDisposeListener(this); - } - } - } - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - } - - @Override - public void mouseUp(MouseEvent e) { - } - - @Override - public void widgetDisposed(DisposeEvent event) { - userMenu = null; - lastDisposeTS = System.currentTimeMillis(); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/VerticalMenu.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/VerticalMenu.java deleted file mode 100644 index 7f846c932..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/VerticalMenu.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.argeo.cms.ui.util; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -public class VerticalMenu implements CmsUiProvider { - private List items = new ArrayList(); - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - Composite part = new Composite(parent, SWT.NONE); - part.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false)); -// part.setData(RWT.CUSTOM_VARIANT, custom); - part.setLayout(CmsSwtUtils.noSpaceGridLayout()); - for (CmsUiProvider uiProvider : items) { - Control subPart = uiProvider.createUi(part, context); - subPart.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false)); - } - return part; - } - - public void add(CmsUiProvider uiProvider) { - items.add(uiProvider); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/package-info.java deleted file mode 100644 index 566df883c..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo CMS UI utilities. */ -package org.argeo.cms.ui.util; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java deleted file mode 100644 index e23846e92..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java +++ /dev/null @@ -1,351 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Observable; -import java.util.Observer; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; - -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.CmsEditable; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.swt.widgets.ScrolledPage; -import org.argeo.jcr.JcrException; -import org.eclipse.jface.viewers.ContentViewer; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Widget; -import org.xml.sax.SAXParseException; - -/** Base class for viewers related to a page */ -public abstract class AbstractPageViewer extends ContentViewer implements Observer { - private static final long serialVersionUID = 5438688173410341485L; - - private final static CmsLog log = CmsLog.getLog(AbstractPageViewer.class); - - private final boolean readOnly; - /** The basis for the layouts, typically a ScrolledPage. */ - private final Composite page; - private final CmsEditable cmsEditable; - - private MouseListener mouseListener; - private FocusListener focusListener; - - private SwtEditablePart edited; - private ISelection selection = StructuredSelection.EMPTY; - - private AccessControlContext accessControlContext; - - protected AbstractPageViewer(Section parent, int style, CmsEditable cmsEditable) { - // read only at UI level - readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY); - - this.cmsEditable = cmsEditable == null ? CmsEditable.NON_EDITABLE : cmsEditable; - if (this.cmsEditable instanceof Observable) - ((Observable) this.cmsEditable).addObserver(this); - - if (cmsEditable.canEdit()) { - mouseListener = createMouseListener(); - focusListener = createFocusListener(); - } - page = findPage(parent); - accessControlContext = AccessController.getContext(); - } - - /** - * Can be called to simplify the called to isModelInitialized() and initModel() - */ - protected void initModelIfNeeded(Node node) { - try { - if (!isModelInitialized(node)) - if (getCmsEditable().canEdit()) { - initModel(node); - node.getSession().save(); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot initialize model", e); - } - } - - /** Called if user can edit and model is not initialized */ - protected Boolean isModelInitialized(Node node) throws RepositoryException { - return true; - } - - /** Called if user can edit and model is not initialized */ - protected void initModel(Node node) throws RepositoryException { - } - - /** Create (retrieve) the MouseListener to use. */ - protected MouseListener createMouseListener() { - return new MouseAdapter() { - private static final long serialVersionUID = 1L; - }; - } - - /** Create (retrieve) the FocusListener to use. */ - protected FocusListener createFocusListener() { - return new FocusListener() { - private static final long serialVersionUID = 1L; - - @Override - public void focusLost(FocusEvent event) { - } - - @Override - public void focusGained(FocusEvent event) { - } - }; - } - - protected Composite findPage(Composite composite) { - if (composite instanceof ScrolledPage) { - return (ScrolledPage) composite; - } else { - if (composite.getParent() == null) - return composite; - return findPage(composite.getParent()); - } - } - - public void layoutPage() { - if (page != null) - page.layout(true, true); - } - - protected void showControl(Control control) { - if (page != null && (page instanceof ScrolledPage)) - ((ScrolledPage) page).showControl(control); - } - - @Override - public void update(Observable o, Object arg) { - if (o == cmsEditable) - editingStateChanged(cmsEditable); - } - - /** To be overridden in order to provide the actual refresh */ - protected void refresh(Control control) throws RepositoryException { - } - - /** To be overridden.Save the edited part. */ - protected void save(SwtEditablePart part) throws RepositoryException { - } - - /** Prepare the edited part */ - protected void prepare(SwtEditablePart part, Object caretPosition) { - } - - /** Notified when the editing state changed. Does nothing, to be overridden */ - protected void editingStateChanged(CmsEditable cmsEditable) { - } - - @Override - public void refresh() { - // TODO check actual context in order to notice a discrepancy - Subject viewerSubject = getViewerSubject(); - Subject.doAs(viewerSubject, (PrivilegedAction) () -> { - try { - if (cmsEditable.canEdit() && !readOnly) - mouseListener = createMouseListener(); - else - mouseListener = null; - refresh(getControl()); - // layout(getControl()); - if (!getControl().isDisposed()) - layoutPage(); - } catch (RepositoryException e) { - throw new JcrException("Cannot refresh", e); - } - return null; - }); - } - - @Override - public void setSelection(ISelection selection, boolean reveal) { - this.selection = selection; - } - - protected void updateContent(SwtEditablePart part) throws RepositoryException { - } - - // LOW LEVEL EDITION - protected void edit(SwtEditablePart part, Object caretPosition) { - try { - if (edited == part) - return; - - if (edited != null && edited != part) { - SwtEditablePart previouslyEdited = edited; - try { - stopEditing(true); - } catch (Exception e) { - notifyEditionException(e); - edit(previouslyEdited, caretPosition); - return; - } - } - - part.startEditing(); - edited = part; - updateContent(part); - prepare(part, caretPosition); - edited.getControl().addFocusListener(new FocusListener() { - private static final long serialVersionUID = 6883521812717097017L; - - @Override - public void focusLost(FocusEvent event) { - stopEditing(true); - } - - @Override - public void focusGained(FocusEvent event) { - } - }); - - layout(part.getControl()); - showControl(part.getControl()); - } catch (RepositoryException e) { - throw new JcrException("Cannot edit " + part, e); - } - } - - protected void stopEditing(Boolean save) { - if (edited instanceof Widget && ((Widget) edited).isDisposed()) { - edited = null; - return; - } - - assert edited != null; - if (edited == null) { - if (log.isTraceEnabled()) - log.warn("Told to stop editing while not editing anything"); - return; - } - - try { - if (save) - save(edited); - - edited.stopEditing(); - SwtEditablePart editablePart = edited; - Control control = ((SwtEditablePart) edited).getControl(); - edited = null; - // TODO make edited state management more robust - updateContent(editablePart); - layout(control); - } catch (RepositoryException e) { - throw new JcrException("Cannot stop editing", e); - } finally { - edited = null; - } - } - - // METHODS AVAILABLE TO EXTENDING CLASSES - protected void saveEdit() { - if (edited != null) - stopEditing(true); - } - - protected void cancelEdit() { - if (edited != null) - stopEditing(false); - } - - /** Layout this controls from the related base page. */ - public void layout(Control... controls) { - page.layout(controls); - } - - /** - * Find the first {@link SwtEditablePart} in the parents hierarchy of this control - */ - protected SwtEditablePart findDataParent(Control parent) { - if (parent instanceof SwtEditablePart) { - return (SwtEditablePart) parent; - } - if (parent.getParent() != null) - return findDataParent(parent.getParent()); - else - throw new IllegalStateException("No data parent found"); - } - - // UTILITIES - /** Check whether the edited part is in a proper state */ - protected void checkEdited() { - if (edited == null || (edited instanceof Widget) && ((Widget) edited).isDisposed()) - throw new IllegalStateException("Edited should not be null or disposed at this stage"); - } - - /** Persist all changes. */ - protected void persistChanges(Session session) throws RepositoryException { - session.save(); - session.refresh(false); - // TODO notify that changes have been persisted - } - - /** Convenience method using a Node in order to save the underlying session. */ - protected void persistChanges(Node anyNode) throws RepositoryException { - persistChanges(anyNode.getSession()); - } - - /** Notify edition exception */ - protected void notifyEditionException(Throwable e) { - Throwable eToLog = e; - if (e instanceof IllegalArgumentException) - if (e.getCause() instanceof SAXParseException) - eToLog = e.getCause(); - log.error(eToLog.getMessage(), eToLog); -// if (log.isTraceEnabled()) -// log.trace("Full stack of " + eToLog.getMessage(), e); - // TODO Light error notification popup - } - - protected Subject getViewerSubject() { - Subject res = null; - if (accessControlContext != null) { - res = Subject.getSubject(accessControlContext); - } - if (res == null) - throw new IllegalStateException("No subject associated with this viewer"); - return res; - } - - // GETTERS / SETTERS - public boolean isReadOnly() { - return readOnly; - } - - protected SwtEditablePart getEdited() { - return edited; - } - - public MouseListener getMouseListener() { - return mouseListener; - } - - public FocusListener getFocusListener() { - return focusListener; - } - - public CmsEditable getCmsEditable() { - return cmsEditable; - } - - @Override - public ISelection getSelection() { - return selection; - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/ItemPart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/ItemPart.java deleted file mode 100644 index 4ca45d191..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/ItemPart.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; - -/** An editable part related to a JCR Item */ -public interface ItemPart { - public Item getItem() throws RepositoryException; -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/JcrVersionCmsEditable.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/JcrVersionCmsEditable.java deleted file mode 100644 index 298fbdea9..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/JcrVersionCmsEditable.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.VersionManager; - -import org.argeo.api.cms.ux.CmsEditionEvent; -import org.argeo.cms.ux.AbstractCmsEditable; -import org.argeo.jcr.JcrException; -import org.eclipse.rap.rwt.RWT; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; - -/** Provides the CmsEditable semantic based on JCR versioning. */ -public class JcrVersionCmsEditable extends AbstractCmsEditable { - private final String nodePath;// cache - private final VersionManager versionManager; - private final Boolean canEdit; - - public JcrVersionCmsEditable(Node node) throws RepositoryException { - this.nodePath = node.getPath(); - if (node.getSession().hasPermission(node.getPath(), Session.ACTION_SET_PROPERTY)) { - // was Session.ACTION_ADD_NODE - canEdit = true; - if (!node.isNodeType(NodeType.MIX_VERSIONABLE)) { - node.addMixin(NodeType.MIX_VERSIONABLE); - node.getSession().save(); - } - versionManager = node.getSession().getWorkspace().getVersionManager(); - } else { - canEdit = false; - versionManager = null; - } - - // bind keys - if (canEdit) { - Display display = Display.getCurrent(); - display.setData(RWT.ACTIVE_KEYS, new String[] { "CTRL+RETURN", "CTRL+E" }); - display.addFilter(SWT.KeyDown, new Listener() { - private static final long serialVersionUID = -4378653870463187318L; - - public void handleEvent(Event e) { - boolean ctrlPressed = (e.stateMask & SWT.CTRL) != 0; - if (ctrlPressed && e.keyCode == '\r') - stopEditing(); - else if (ctrlPressed && e.keyCode == 'E') - stopEditing(); - } - }); - } - } - - @Override - public Boolean canEdit() { - return canEdit; - } - - public Boolean isEditing() { - try { - if (!canEdit()) - return false; - return versionManager.isCheckedOut(nodePath); - } catch (RepositoryException e) { - throw new JcrException("Cannot check whether " + nodePath + " is editing", e); - } - } - - @Override - public void startEditing() { - try { - versionManager.checkout(nodePath); -// setChanged(); - } catch (RepositoryException e1) { - throw new JcrException("Cannot publish " + nodePath, e1); - } - notifyListeners(new CmsEditionEvent(nodePath, CmsEditionEvent.START_EDITING, this)); - } - - @Override - public void stopEditing() { - try { - versionManager.checkin(nodePath); -// setChanged(); - } catch (RepositoryException e1) { - throw new JcrException("Cannot publish " + nodePath, e1); - } - notifyListeners(new CmsEditionEvent(nodePath, CmsEditionEvent.STOP_EDITING, this)); - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/NodePart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/NodePart.java deleted file mode 100644 index b51d4fcba..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/NodePart.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import javax.jcr.Node; - -/** An editable part related to a node */ -public interface NodePart extends ItemPart { - public Node getNode(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/PropertyPart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/PropertyPart.java deleted file mode 100644 index 793079e20..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/PropertyPart.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import javax.jcr.Property; - -/** An editable part related to a JCR Property */ -public interface PropertyPart extends ItemPart { - public Property getProperty(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/Section.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/Section.java deleted file mode 100644 index b27fa3845..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/Section.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.SwtEditablePart; -import org.argeo.cms.ui.widgets.JcrComposite; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** A structured UI related to a JCR context. */ -public class Section extends JcrComposite { - private static final long serialVersionUID = -5933796173755739207L; - - private final Section parentSection; - private Composite sectionHeader; - private final Integer relativeDepth; - - public Section(Composite parent, int style, Node node) { - this(parent, findSection(parent), style, node); - } - - public Section(Section section, int style, Node node) { - this(section, section, style, node); - } - - protected Section(Composite parent, Section parentSection, int style, Node node) { - super(parent, style, node); - try { - this.parentSection = parentSection; - if (parentSection != null) { - relativeDepth = getNode().getDepth() - parentSection.getNode().getDepth(); - } else { - relativeDepth = 0; - } - setLayout(CmsSwtUtils.noSpaceGridLayout()); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot create section from " + node, e); - } - } - - public Map getSubSections() throws RepositoryException { - LinkedHashMap result = new LinkedHashMap(); - for (Control child : getChildren()) { - if (child instanceof Composite) { - collectDirectSubSections((Composite) child, result); - } - } - return Collections.unmodifiableMap(result); - } - - private void collectDirectSubSections(Composite composite, LinkedHashMap subSections) - throws RepositoryException { - if (composite == sectionHeader || composite instanceof SwtEditablePart) - return; - if (composite instanceof Section) { - Section section = (Section) composite; - subSections.put(section.getNodeId(), section); - return; - } - - for (Control child : composite.getChildren()) - if (child instanceof Composite) - collectDirectSubSections((Composite) child, subSections); - } - - public Composite createHeader() { - return createHeader(this); - } - - public Composite createHeader(Composite parent) { - if (sectionHeader != null) - sectionHeader.dispose(); - - sectionHeader = new Composite(parent, SWT.NONE); - sectionHeader.setLayoutData(CmsSwtUtils.fillWidth()); - sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout()); - // sectionHeader.moveAbove(null); - // layout(); - return sectionHeader; - } - - public Composite getHeader() { - if (sectionHeader != null && sectionHeader.isDisposed()) - sectionHeader = null; - return sectionHeader; - } - - // SECTION PARTS - public SectionPart getSectionPart(String partId) { - for (Control child : getChildren()) { - if (child instanceof SectionPart) { - SectionPart sectionPart = (SectionPart) child; - if (sectionPart.getPartId().equals(partId)) - return sectionPart; - } - } - return null; - } - - public SectionPart nextSectionPart(SectionPart sectionPart) { - Control[] children = getChildren(); - for (int i = 0; i < children.length; i++) { - if (sectionPart == children[i]) { - for (int j = i + 1; j < children.length; j++) { - if (children[i + 1] instanceof SectionPart) { - return (SectionPart) children[i + 1]; - } - } - -// if (i + 1 < children.length) { -// Composite next = (Composite) children[i + 1]; -// return (SectionPart) next; -// } else { -// // next section -// } - } - } - return null; - } - - public SectionPart previousSectionPart(SectionPart sectionPart) { - Control[] children = getChildren(); - for (int i = 0; i < children.length; i++) { - if (sectionPart == children[i]) - if (i != 0) { - Composite previous = (Composite) children[i - 1]; - return (SectionPart) previous; - } else { - // previous section - } - } - return null; - } - - @Override - public String toString() { - if (parentSection == null) - return "Main section " + getNode(); - return "Section " + getNode(); - } - - public Section getParentSection() { - return parentSection; - } - - public Integer getRelativeDepth() { - return relativeDepth; - } - - /** Recursively finds the related section in the parents (can be itself) */ - public static Section findSection(Control control) { - if (control == null) - return null; - if (control instanceof Section) - return (Section) control; - else - return findSection(control.getParent()); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/SectionPart.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/SectionPart.java deleted file mode 100644 index 4278c83cc..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/SectionPart.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.argeo.cms.ui.viewers; - -import org.argeo.cms.swt.SwtEditablePart; - -/** An editable part dynamically related to a Section */ -public interface SectionPart extends SwtEditablePart, NodePart { - public String getPartId(); - - public Section getSection(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/package-info.java deleted file mode 100644 index 2f0793127..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/viewers/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo CMS generic viewers, based on JFace. */ -package org.argeo.cms.ui.viewers; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableImage.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableImage.java deleted file mode 100644 index 95d9e8ee9..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableImage.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.argeo.cms.ui.widgets; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** A stylable and editable image. */ -public abstract class EditableImage extends StyledControl { - private static final long serialVersionUID = -5689145523114022890L; - private final static CmsLog log = CmsLog.getLog(EditableImage.class); - - private Cms2DSize preferredImageSize; - private Boolean loaded = false; - - public EditableImage(Composite parent, int swtStyle) { - super(parent, swtStyle); - } - - public EditableImage(Composite parent, int swtStyle, Cms2DSize preferredImageSize) { - super(parent, swtStyle); - this.preferredImageSize = preferredImageSize; - } - - public EditableImage(Composite parent, int style, Node node, boolean cacheImmediately, Cms2DSize preferredImageSize) - throws RepositoryException { - super(parent, style, node, cacheImmediately); - this.preferredImageSize = preferredImageSize; - } - - @Override - protected void setContainerLayoutData(Composite composite) { - // composite.setLayoutData(fillWidth()); - } - - @Override - protected void setControlLayoutData(Control control) { - // control.setLayoutData(fillWidth()); - } - - /** To be overriden. */ - protected String createImgTag() throws RepositoryException { - return CmsUiUtils - .noImg(preferredImageSize != null ? preferredImageSize : new Cms2DSize(getSize().x, getSize().y)); - } - - protected Label createLabel(Composite box, String style) { - Label lbl = new Label(box, getStyle()); - // lbl.setLayoutData(CmsUiUtils.fillWidth()); - CmsSwtUtils.markup(lbl); - CmsSwtUtils.style(lbl, style); - if (mouseListener != null) - lbl.addMouseListener(mouseListener); - load(lbl); - return lbl; - } - - /** To be overriden. */ - protected synchronized Boolean load(Control control) { - String imgTag; - try { - imgTag = createImgTag(); - } catch (Exception e) { - // throw new CmsException("Cannot retrieve image", e); - log.error("Cannot retrieve image", e); - imgTag = CmsUiUtils.noImg(preferredImageSize); - loaded = false; - } - - if (imgTag == null) { - loaded = false; - imgTag = CmsUiUtils.noImg(preferredImageSize); - } else - loaded = true; - if (control != null) { - ((Label) control).setText(imgTag); - control.setSize(preferredImageSize != null - ? new Point(preferredImageSize.getWidth(), preferredImageSize.getHeight()) - : getSize()); - } else { - loaded = false; - } - getParent().layout(); - return loaded; - } - - public void setPreferredSize(Cms2DSize size) { - this.preferredImageSize = size; - if (!loaded) { - load((Label) getControl()); - } - } - - protected Text createText(Composite box, String style) { - Text text = new Text(box, getStyle()); - CmsSwtUtils.style(text, style); - return text; - } - - public Cms2DSize getPreferredImageSize() { - return preferredImageSize; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableText.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableText.java deleted file mode 100644 index e3499ac4b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/EditableText.java +++ /dev/null @@ -1,145 +0,0 @@ -package org.argeo.cms.ui.widgets; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** Editable text part displaying styled text. */ -public class EditableText extends StyledControl { - private static final long serialVersionUID = -6372283442330912755L; - - private boolean editable = true; - - private Color highlightColor; - private Composite highlight; - - private boolean useTextAsLabel = false; - - public EditableText(Composite parent, int style) { - super(parent, style); - editable = !(SWT.READ_ONLY == (style & SWT.READ_ONLY)); - highlightColor = parent.getDisplay().getSystemColor(SWT.COLOR_GRAY); - } - - public EditableText(Composite parent, int style, Item item) throws RepositoryException { - this(parent, style, item, false); - } - - public EditableText(Composite parent, int style, Item item, boolean cacheImmediately) throws RepositoryException { - super(parent, style, item, cacheImmediately); - editable = !(SWT.READ_ONLY == (style & SWT.READ_ONLY)); - highlightColor = parent.getDisplay().getSystemColor(SWT.COLOR_GRAY); - } - - @Override - protected Control createControl(Composite box, String style) { - if (isEditing() && getEditable()) { - return createText(box, style, true); - } else { - if (useTextAsLabel) { - return createTextLabel(box, style); - } else { - return createLabel(box, style); - } - } - } - - protected Label createLabel(Composite box, String style) { - Label lbl = new Label(box, getStyle() | SWT.WRAP); - lbl.setLayoutData(CmsSwtUtils.fillWidth()); - if (style != null) - CmsSwtUtils.style(lbl, style); - CmsSwtUtils.markup(lbl); - if (mouseListener != null) - lbl.addMouseListener(mouseListener); - return lbl; - } - - protected Text createTextLabel(Composite box, String style) { - Text lbl = new Text(box, getStyle() | SWT.MULTI); - lbl.setEditable(false); - lbl.setLayoutData(CmsSwtUtils.fillWidth()); - if (style != null) - CmsSwtUtils.style(lbl, style); - CmsSwtUtils.markup(lbl); - if (mouseListener != null) - lbl.addMouseListener(mouseListener); - return lbl; - } - - protected Text createText(Composite box, String style, boolean editable) { - highlight = new Composite(box, SWT.NONE); - highlight.setBackground(highlightColor); - GridData highlightGd = new GridData(SWT.FILL, SWT.FILL, false, false); - highlightGd.widthHint = 5; - highlightGd.heightHint = 3; - highlight.setLayoutData(highlightGd); - - final Text text = new Text(box, getStyle() | SWT.MULTI | SWT.WRAP); - text.setEditable(editable); - GridData textLayoutData = CmsSwtUtils.fillWidth(); - // textLayoutData.heightHint = preferredHeight; - text.setLayoutData(textLayoutData); - if (style != null) - CmsSwtUtils.style(text, style); - text.setFocus(); - return text; - } - - @Override - protected void clear(boolean deep) { - if (highlight != null) - highlight.dispose(); - super.clear(deep); - } - - public void setText(String text) { - Control child = getControl(); - if (child instanceof Label) - ((Label) child).setText(text); - else if (child instanceof Text) - ((Text) child).setText(text); - } - - public Text getAsText() { - return (Text) getControl(); - } - - public Label getAsLabel() { - return (Label) getControl(); - } - - public String getText() { - Control child = getControl(); - - if (child instanceof Label) - return ((Label) child).getText(); - else if (child instanceof Text) - return ((Text) child).getText(); - else - throw new IllegalStateException("Unsupported control " + child.getClass()); - } - - /** @deprecated Use {@link #isEditable()} instead. */ - @Deprecated - public boolean getEditable() { - return isEditable(); - } - - public boolean isEditable() { - return editable; - } - - public void setUseTextAsLabel(boolean useTextAsLabel) { - this.useTextAsLabel = useTextAsLabel; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/Img.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/Img.java deleted file mode 100644 index 41063fa47..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/Img.java +++ /dev/null @@ -1,155 +0,0 @@ -package org.argeo.cms.ui.widgets; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.api.cms.ux.CmsImageManager; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.internal.JcrFileUploadReceiver; -import org.argeo.cms.ui.viewers.NodePart; -import org.argeo.cms.ui.viewers.Section; -import org.argeo.cms.ui.viewers.SectionPart; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.eclipse.rap.fileupload.FileUploadHandler; -import org.eclipse.rap.fileupload.FileUploadListener; -import org.eclipse.rap.fileupload.FileUploadReceiver; -import org.eclipse.rap.rwt.service.ServerPushSession; -import org.eclipse.rap.rwt.widgets.FileUpload; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** An image within the Argeo Text framework */ -public class Img extends EditableImage implements SectionPart, NodePart { - private static final long serialVersionUID = 6233572783968188476L; - - private final Section section; - - private final CmsImageManager imageManager; - private FileUploadHandler currentUploadHandler = null; - private FileUploadListener fileUploadListener; - - public Img(Composite parent, int swtStyle, Node imgNode, Cms2DSize preferredImageSize) throws RepositoryException { - this(Section.findSection(parent), parent, swtStyle, imgNode, preferredImageSize, null); - setStyle(TextStyles.TEXT_IMAGE); - } - - public Img(Composite parent, int swtStyle, Node imgNode) throws RepositoryException { - this(Section.findSection(parent), parent, swtStyle, imgNode, null, null); - setStyle(TextStyles.TEXT_IMAGE); - } - - public Img(Composite parent, int swtStyle, Node imgNode, CmsImageManager imageManager) - throws RepositoryException { - this(Section.findSection(parent), parent, swtStyle, imgNode, null, imageManager); - setStyle(TextStyles.TEXT_IMAGE); - } - - Img(Section section, Composite parent, int swtStyle, Node imgNode, Cms2DSize preferredImageSize, - CmsImageManager imageManager) throws RepositoryException { - super(parent, swtStyle, imgNode, false, preferredImageSize); - this.section = section; - this.imageManager = imageManager != null ? imageManager - : (CmsImageManager) CmsSwtUtils.getCmsView(section).getImageManager(); - CmsSwtUtils.style(this, TextStyles.TEXT_IMG); - } - - @Override - protected Control createControl(Composite box, String style) { - if (isEditing()) { - try { - return createImageChooser(box, style); - } catch (RepositoryException e) { - throw new JcrException("Cannot create image chooser", e); - } - } else { - return createLabel(box, style); - } - } - - @Override - public synchronized void stopEditing() { - super.stopEditing(); - fileUploadListener = null; - } - - @Override - protected synchronized Boolean load(Control lbl) { - Node imgNode = getNode(); - boolean loaded = imageManager.load(imgNode, lbl, getPreferredImageSize()); - // getParent().layout(); - return loaded; - } - - protected Node getUploadFolder() { - return Jcr.getParent(getNode()); - } - - protected String getUploadName() { - Node node = getNode(); - return Jcr.getName(node) + '[' + Jcr.getIndex(node) + ']'; - } - - protected CmsImageManager getImageManager() { - return imageManager; - } - - protected Control createImageChooser(Composite box, String style) throws RepositoryException { - JcrFileUploadReceiver receiver = new JcrFileUploadReceiver(this, getUploadFolder(), getUploadName(), - imageManager); - if (currentUploadHandler != null) - currentUploadHandler.dispose(); - currentUploadHandler = prepareUpload(receiver); - final ServerPushSession pushSession = new ServerPushSession(); - final FileUpload fileUpload = new FileUpload(box, SWT.NONE); - CmsSwtUtils.style(fileUpload, style); - fileUpload.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -9158471843941668562L; - - @Override - public void widgetSelected(SelectionEvent e) { - pushSession.start(); - fileUpload.submit(currentUploadHandler.getUploadUrl()); - } - }); - return fileUpload; - } - - protected FileUploadHandler prepareUpload(FileUploadReceiver receiver) { - final FileUploadHandler uploadHandler = new FileUploadHandler(receiver); - if (fileUploadListener != null) - uploadHandler.addUploadListener(fileUploadListener); - return uploadHandler; - } - - @Override - public Section getSection() { - return section; - } - - public void setFileUploadListener(FileUploadListener fileUploadListener) { - this.fileUploadListener = fileUploadListener; - if (currentUploadHandler != null) - currentUploadHandler.addUploadListener(fileUploadListener); - } - - @Override - public Node getItem() throws RepositoryException { - return getNode(); - } - - @Override - public String getPartId() { - return getNodeId(); - } - - @Override - public String toString() { - return "Img #" + getPartId(); - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/JcrComposite.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/JcrComposite.java deleted file mode 100644 index 6b54c0a7b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/JcrComposite.java +++ /dev/null @@ -1,213 +0,0 @@ -package org.argeo.cms.ui.widgets; - -import javax.jcr.Item; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.jcr.JcrException; -import org.eclipse.swt.widgets.Composite; - -/** A composite which can (optionally) manage a JCR Item. */ -public class JcrComposite extends Composite { - private static final long serialVersionUID = -1447009015451153367L; - - private Session session; - - private String nodeId; - private String property = null; - private Node cache; - - /** Regular composite constructor. No layout is set. */ - public JcrComposite(Composite parent, int style) { - super(parent, style); - session = null; - nodeId = null; - } - - public JcrComposite(Composite parent, int style, Item item) { - this(parent, style, item, false); - } - - public JcrComposite(Composite parent, int style, Item item, boolean cacheImmediately) { - super(parent, style); - if (item != null) - try { - this.session = item.getSession(); -// if (!cacheImmediately && (SWT.READ_ONLY == (style & SWT.READ_ONLY))) { -// // (useless?) optimization: we only save a pointer to the session, -// // not even a reference to the item -// this.nodeId = null; -// } else { - Node node; - Property property = null; - if (item instanceof Node) { - node = (Node) item; - } else {// Property - property = (Property) item; - if (property.isMultiple())// TODO manage property index - throw new UnsupportedOperationException("Multiple properties not supported yet."); - this.property = property.getName(); - node = property.getParent(); - } - this.nodeId = node.getIdentifier(); - if (cacheImmediately) - this.cache = node; -// } - setLayout(CmsSwtUtils.noSpaceGridLayout()); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot create composite from " + item, e); - } - } - - public synchronized Node getNode() { - try { - if (!itemIsNode()) - throw new IllegalStateException("Item is not a Node"); - return getNodeInternal(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get node " + nodeId, e); - } - } - - private synchronized Node getNodeInternal() throws RepositoryException { - if (cache != null) - return cache; - else if (session != null) - if (nodeId != null) - return session.getNodeByIdentifier(nodeId); - else - return null; - else - return null; - } - - public synchronized String getPropertyName() { - try { - return getProperty().getName(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property name", e); - } - } - - public synchronized Node getPropertyNode() { - try { - return getProperty().getNode(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property name", e); - } - } - - public synchronized Property getProperty() { - try { - if (itemIsNode()) - throw new IllegalStateException("Item is not a Property"); - Node node = getNodeInternal(); - if (!node.hasProperty(property)) - throw new IllegalStateException("Property " + property + " is not set on " + node); - return node.getProperty(property); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property " + property + " from node " + nodeId, e); - } - } - - public synchronized boolean itemIsNode() { - return property == null; - } - - public synchronized boolean itemExists() { - if (session == null) - return false; - try { - Node n = session.getNodeByIdentifier(nodeId); - if (!itemIsNode()) - return n.hasProperty(property); - else - return true; - } catch (ItemNotFoundException e) { - return false; - } catch (RepositoryException e) { - throw new JcrException("Cannot check whether node exists", e); - } - } - - /** Set/update the cache or change the node */ - public synchronized void setNode(Node node) { - if (!itemIsNode()) - throw new IllegalArgumentException("Cannot set a Node on a Property"); - - if (node == null) {// clear cache - this.cache = null; - return; - } - - try { -// if (session != null || session != node.getSession())// check session -// throw new IllegalArgumentException("Uncompatible session"); -// if (session == null) - session = node.getSession(); - if (nodeId == null || !nodeId.equals(node.getIdentifier())) { - nodeId = node.getIdentifier(); - cache = node; - itemUpdated(); - } else { - cache = node;// set/update cache - } - } catch (RepositoryException e) { - throw new IllegalStateException(e); - } - } - - /** Set/update the cache or change the property */ - public synchronized void setProperty(Property prop) { - if (itemIsNode()) - throw new IllegalArgumentException("Cannot set a Property on a Node"); - - if (prop == null) {// clear cache - this.cache = null; - return; - } - - try { - if (session == null || session != prop.getSession())// check session - throw new IllegalArgumentException("Uncompatible session"); - - Node node = prop.getNode(); - if (nodeId == null || !nodeId.equals(node.getIdentifier()) || !property.equals(prop.getName())) { - nodeId = node.getIdentifier(); - property = prop.getName(); - cache = node; - itemUpdated(); - } else { - cache = node;// set/update cache - } - } catch (RepositoryException e) { - throw new IllegalStateException(e); - } - } - - public synchronized String getNodeId() { - return nodeId; - } - - /** Change the node, does nothing if same. */ - public synchronized void setNodeId(String nodeId) throws RepositoryException { - if (this.nodeId != null && this.nodeId.equals(nodeId)) - return; - this.nodeId = nodeId; - if (cache != null) - cache = session.getNodeByIdentifier(this.nodeId); - itemUpdated(); - } - - protected synchronized void itemUpdated() { - layout(); - } - -// public Session getSession() { -// return session; -// } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/StyledControl.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/StyledControl.java deleted file mode 100644 index e3a5cb473..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/StyledControl.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.argeo.cms.ui.widgets; - -import javax.jcr.Item; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiConstants; -import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** Editable text part displaying styled text. */ -public abstract class StyledControl extends JcrComposite implements CmsUiConstants { - private static final long serialVersionUID = -6372283442330912755L; - private Control control; - - private Composite container; - private Composite box; - - protected MouseListener mouseListener; - protected FocusListener focusListener; - - private Boolean editing = Boolean.FALSE; - - private Composite ancestorToLayout; - - public StyledControl(Composite parent, int swtStyle) { - super(parent, swtStyle); - setLayout(CmsSwtUtils.noSpaceGridLayout()); - } - - public StyledControl(Composite parent, int style, Item item) { - super(parent, style, item); - } - - public StyledControl(Composite parent, int style, Item item, boolean cacheImmediately) { - super(parent, style, item, cacheImmediately); - } - - protected abstract Control createControl(Composite box, String style); - - protected Composite createBox() { - Composite box = new Composite(container, SWT.INHERIT_DEFAULT); - setContainerLayoutData(box); - box.setLayout(CmsSwtUtils.noSpaceGridLayout(3)); - return box; - } - - protected Composite createContainer() { - Composite container = new Composite(this, SWT.INHERIT_DEFAULT); - setContainerLayoutData(container); - container.setLayout(CmsSwtUtils.noSpaceGridLayout()); - return container; - } - - public Control getControl() { - return control; - } - - protected synchronized Boolean isEditing() { - return editing; - } - - public synchronized void startEditing() { - assert !isEditing(); - editing = true; - // int height = control.getSize().y; - String style = (String) EclipseUiSpecificUtils.getStyleData(control); - clear(false); - refreshControl(style); - - // add the focus listener to the newly created edition control - if (focusListener != null) - control.addFocusListener(focusListener); - } - - public synchronized void stopEditing() { - assert isEditing(); - editing = false; - String style = (String) EclipseUiSpecificUtils.getStyleData(control); - clear(false); - refreshControl(style); - } - - protected void refreshControl(String style) { - control = createControl(box, style); - setControlLayoutData(control); - if (ancestorToLayout != null) - ancestorToLayout.layout(true, true); - else - getParent().layout(true, true); - } - - public void setStyle(String style) { - Object currentStyle = null; - if (control != null) - currentStyle = EclipseUiSpecificUtils.getStyleData(control); - if (currentStyle != null && currentStyle.equals(style)) - return; - - clear(true); - refreshControl(style); - - if (style != null) { - CmsSwtUtils.style(box, style + "_box"); - CmsSwtUtils.style(container, style + "_container"); - } - } - - /** To be overridden */ - protected void setControlLayoutData(Control control) { - control.setLayoutData(CmsSwtUtils.fillWidth()); - } - - /** To be overridden */ - protected void setContainerLayoutData(Composite composite) { - composite.setLayoutData(CmsSwtUtils.fillWidth()); - } - - protected void clear(boolean deep) { - if (deep) { - for (Control control : getChildren()) - control.dispose(); - container = createContainer(); - box = createBox(); - } else { - control.dispose(); - } - } - - public void setMouseListener(MouseListener mouseListener) { - if (this.mouseListener != null && control != null) - control.removeMouseListener(this.mouseListener); - this.mouseListener = mouseListener; - if (control != null && this.mouseListener != null) - control.addMouseListener(mouseListener); - } - - public void setFocusListener(FocusListener focusListener) { - if (this.focusListener != null && control != null) - control.removeFocusListener(this.focusListener); - this.focusListener = focusListener; - if (control != null && this.focusListener != null) - control.addFocusListener(focusListener); - } - - public void setAncestorToLayout(Composite ancestorToLayout) { - this.ancestorToLayout = ancestorToLayout; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/TextStyles.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/TextStyles.java deleted file mode 100644 index e461ed0df..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/TextStyles.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.argeo.cms.ui.widgets; - -/** Styles references in the CSS. */ -public interface TextStyles { - /** The whole page area */ - public final static String TEXT_AREA = "text_area"; - /** Area providing controls for editing text */ - public final static String TEXT_EDITOR_HEADER = "text_editor_header"; - /** The styled composite for editing the text */ - public final static String TEXT_STYLED_COMPOSITE = "text_styled_composite"; - /** A section */ - public final static String TEXT_SECTION = "text_section"; - /** A paragraph */ - public final static String TEXT_PARAGRAPH = "text_paragraph"; - /** An image */ - public final static String TEXT_IMG = "text_img"; - /** The dialog to edit styled paragraph */ - public final static String TEXT_STYLED_TOOLS_DIALOG = "text_styled_tools_dialog"; - - /* - * DEFAULT TEXT STYLES - */ - /** Default style for text body */ - public final static String TEXT_DEFAULT = "text_default"; - /** Fixed-width, typically code */ - public final static String TEXT_PRE = "text_pre"; - /** Quote */ - public final static String TEXT_QUOTE = "text_quote"; - /** Title */ - public final static String TEXT_TITLE = "text_title"; - /** Header (to be dynamically completed with the depth, e.g. text_h1) */ - public final static String TEXT_H = "text_h"; - - /** Default style for images */ - public final static String TEXT_IMAGE = "text_image"; - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/package-info.java deleted file mode 100644 index 514f75380..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/widgets/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo CMS generic widgets, based on SWT. */ -package org.argeo.cms.ui.widgets; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java deleted file mode 100644 index fdafa982e..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.cms.CmsLog; -import org.argeo.eclipse.ui.AbstractTreeContentProvider; -import org.argeo.eclipse.ui.EclipseUiException; - -/** Canonical implementation of tree content provider manipulating JCR nodes. */ -public abstract class AbstractNodeContentProvider extends - AbstractTreeContentProvider { - private static final long serialVersionUID = -4905836490027272569L; - - private final static CmsLog log = CmsLog - .getLog(AbstractNodeContentProvider.class); - - private Session session; - - public AbstractNodeContentProvider(Session session) { - this.session = session; - } - - /** - * Whether this path is a base path (and thus has no parent). By default it - * returns true if path is '/' (root node) - */ - protected Boolean isBasePath(String path) { - // root node - return path.equals("/"); - } - - @Override - public Object[] getChildren(Object element) { - Object[] children; - if (element instanceof Node) { - try { - Node node = (Node) element; - children = getChildren(node); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get children of " + element, e); - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - try { - children = getChildren(wrappedNode.getNode()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get children of " - + wrappedNode, e); - } - } else if (element instanceof NodesWrapper) { - NodesWrapper node = (NodesWrapper) element; - children = node.getChildren(); - } else { - children = super.getChildren(element); - } - - children = sort(element, children); - return children; - } - - /** Do not sort by default. To be overidden to provide custom sort. */ - protected Object[] sort(Object parent, Object[] children) { - return children; - } - - /** - * To be overridden in order to filter out some nodes. Does nothing by - * default. The provided list is a temporary one and can thus be modified - * directly . (e.g. via an iterator) - */ - protected List filterChildren(List children) - throws RepositoryException { - return children; - } - - protected Object[] getChildren(Node node) throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = node.getNodes(); nit.hasNext();) - nodes.add(nit.nextNode()); - nodes = filterChildren(nodes); - return nodes.toArray(); - } - - @Override - public Object getParent(Object element) { - if (element instanceof Node) { - Node node = (Node) element; - try { - String path = node.getPath(); - if (isBasePath(path)) - return null; - else - return node.getParent(); - } catch (RepositoryException e) { - log.warn("Cannot get parent of " + element + ": " + e); - return null; - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getParent(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return this.getParent(nodesWrapper.getNode()); - } - return super.getParent(element); - } - - @Override - public boolean hasChildren(Object element) { - try { - if (element instanceof Node) { - Node node = (Node) element; - return node.hasNodes(); - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getNode().hasNodes(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return nodesWrapper.hasChildren(); - } - - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check whether " + element - + " has children", e); - } - return super.hasChildren(element); - } - - public Session getSession() { - return session; - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java deleted file mode 100644 index b880a63c5..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; - -import org.argeo.api.cms.CmsLog; -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.swt.widgets.Display; - -/** - * {@link EventListener} which simplifies running actions within the UI thread. - */ -public abstract class AsyncUiEventListener implements EventListener { - // private final static Log logSuper = LogFactory - // .getLog(AsyncUiEventListener.class); - private final CmsLog logThis = CmsLog.getLog(getClass()); - - private final Display display; - - public AsyncUiEventListener(Display display) { - super(); - this.display = display; - } - - /** Called asynchronously in the UI thread. */ - protected abstract void onEventInUiThread(List events) throws RepositoryException; - - /** - * Whether these events should be processed in the UI or skipped with no UI - * job created. - */ - protected Boolean willProcessInUiThread(List events) throws RepositoryException { - return true; - } - - protected CmsLog getLog() { - return logThis; - } - - public final void onEvent(final EventIterator eventIterator) { - final List events = new ArrayList(); - while (eventIterator.hasNext()) - events.add(eventIterator.nextEvent()); - - if (logThis.isTraceEnabled()) - logThis.trace("Received " + events.size() + " events"); - - try { - if (!willProcessInUiThread(events)) - return; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot test skip events " + events, e); - } - - // Job job = new Job("JCR Events") { - // protected IStatus run(IProgressMonitor monitor) { - // if (display.isDisposed()) { - // logSuper.warn("Display is disposed cannot update UI"); - // return Status.CANCEL_STATUS; - // } - - if (!display.isDisposed()) - display.asyncExec(new Runnable() { - public void run() { - try { - onEventInUiThread(events); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot process events " + events, e); - } - } - }); - - // return Status.OK_STATUS; - // } - // }; - // job.schedule(); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java deleted file mode 100644 index 22ffeafc6..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** - * Default label provider to manage node and corresponding UI objects. It - * provides reasonable overwrite-able default for known JCR types. - */ -public class DefaultNodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = 1216182332792151235L; - - public String getText(Object element) { - try { - if (element instanceof Node) { - return getText((Node) element); - } else if (element instanceof WrappedNode) { - return getText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getText(((NodesWrapper) element).getNode()); - } - return super.getText(element); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get text for of " + element, e); - } - } - - protected String getText(Node node) throws RepositoryException { - if (node.isNodeType(NodeType.MIX_TITLE) - && node.hasProperty(Property.JCR_TITLE)) - return node.getProperty(Property.JCR_TITLE).getString(); - else - return node.getName(); - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Node) { - return getImage((Node) element); - } else if (element instanceof WrappedNode) { - return getImage(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getImage(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot retrieve image for " + element, e); - } - return super.getImage(element); - } - - protected Image getImage(Node node) throws RepositoryException { - // FIXME who uses that? - return null; - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Node) { - return getToolTipText((Node) element); - } else if (element instanceof WrappedNode) { - return getToolTipText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getToolTipText(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get tooltip for " + element, e); - } - return super.getToolTipText(element); - } - - protected String getToolTipText(Node node) throws RepositoryException { - return null; - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java deleted file mode 100644 index 420154b83..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; -import org.argeo.eclipse.ui.jcr.lists.RowViewerComparator; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Table; - -/** Utility methods to simplify UI development using SWT (or RWT), jface and JCR. */ -public class JcrUiUtils { - - /** - * Centralizes management of updating property value. Among other to avoid - * infinite loop when the new value is the same as the ones that is already - * stored in JCR. - * - * @return true if the value as changed - */ - public static boolean setJcrProperty(Node node, String propName, - int propertyType, Object value) { - try { - switch (propertyType) { - case PropertyType.STRING: - if ("".equals((String) value) - && (!node.hasProperty(propName) || node - .hasProperty(propName) - && "".equals(node.getProperty(propName) - .getString()))) - // workaround the fact that the Text widget value cannot be - // set to null - return false; - else if (node.hasProperty(propName) - && node.getProperty(propName).getString() - .equals((String) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (String) value); - return true; - } - case PropertyType.BOOLEAN: - if (node.hasProperty(propName) - && node.getProperty(propName).getBoolean() == (Boolean) value) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Boolean) value); - return true; - } - case PropertyType.DATE: - if (node.hasProperty(propName) - && node.getProperty(propName).getDate() - .equals((Calendar) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Calendar) value); - return true; - } - case PropertyType.LONG: - Long lgValue = (Long) value; - - if (lgValue == null) - lgValue = 0L; - - if (node.hasProperty(propName) - && node.getProperty(propName).getLong() == lgValue) - // nothing changed yet - return false; - else { - node.setProperty(propName, lgValue); - return true; - } - - default: - throw new EclipseUiException("Unimplemented property save"); - } - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error while setting property", - re); - } - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * SWT Table that display a row list - **/ - public static SelectionAdapter getRowSelectionAdapter(final int index, - final int propertyType, final String selectorName, - final String propertyName, final RowViewerComparator comparator, - final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = -5738918304901437720L; - - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, selectorName, propertyName); - 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; - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * swt table that display a row list - **/ - public static SelectionAdapter getNodeSelectionAdapter(final int index, - final int propertyType, final String propertyName, - final NodeViewerComparator comparator, final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = -1683220869195484625L; - - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, propertyName); - 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; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java deleted file mode 100644 index 7e12becd8..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; - -/** Simplifies writing JCR-based column label provider. */ -public class NodeColumnLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -6586692836928505358L; - - protected String getNodeText(Node node) throws RepositoryException { - return super.getText(node); - } - - protected String getNodeToolTipText(Node node) throws RepositoryException { - return super.getToolTipText(node); - } - - protected Image getNodeImage(Node node) throws RepositoryException { - return super.getImage(node); - } - - protected Font getNodeFont(Node node) throws RepositoryException { - return super.getFont(node); - } - - public Color getNodeBackground(Node node) throws RepositoryException { - return super.getBackground(node); - } - - public Color getNodeForeground(Node node) throws RepositoryException { - return super.getForeground(node); - } - - @Override - public String getText(Object element) { - try { - if (element instanceof Node) - return getNodeText((Node) element); - else if (element instanceof NodeElement) - return getNodeText(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Node) - return getNodeImage((Node) element); - else if (element instanceof NodeElement) - return getNodeImage(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Node) - return getNodeToolTipText((Node) element); - else if (element instanceof NodeElement) - return getNodeToolTipText(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Font getFont(Object element) { - try { - if (element instanceof Node) - return getNodeFont((Node) element); - else if (element instanceof NodeElement) - return getNodeFont(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getBackground(Object element) { - try { - if (element instanceof Node) - return getNodeBackground((Node) element); - else if (element instanceof NodeElement) - return getNodeBackground(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getForeground(Object element) { - try { - if (element instanceof Node) - return getNodeForeground((Node) element); - else if (element instanceof NodeElement) - return getNodeForeground(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java deleted file mode 100644 index 787c92ed5..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; - -/** An element which is related to a JCR {@link Node}. */ -public interface NodeElement { - Node getNode(); -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java deleted file mode 100644 index 2f3d64d6b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Element comparer for JCR node, to be used in JFace viewers. */ -public class NodeElementComparer implements IElementComparer { - - public boolean equals(Object a, Object b) { - try { - if ((a instanceof Node) && (b instanceof Node)) { - Node nodeA = (Node) a; - Node nodeB = (Node) b; - return nodeA.getIdentifier().equals(nodeB.getIdentifier()); - } else { - return a.equals(b); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot compare nodes", e); - } - } - - public int hashCode(Object element) { - try { - if (element instanceof Node) - return ((Node) element).getIdentifier().hashCode(); - return element.hashCode(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get hash code", e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java deleted file mode 100644 index 2f808a51f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** - * Element of tree which is based on a node, but whose children are not - * necessarily this node children. - */ -public class NodesWrapper { - private final Node node; - - public NodesWrapper(Node node) { - super(); - this.node = node; - } - - protected NodeIterator getNodeIterator() throws RepositoryException { - return node.getNodes(); - } - - protected List getWrappedNodes() throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = getNodeIterator(); nit.hasNext();) - nodes.add(new WrappedNode(this, nit.nextNode())); - return nodes; - } - - public Object[] getChildren() { - try { - return getWrappedNodes().toArray(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get wrapped children", e); - } - } - - /** - * @return true by default because we don't want to compute the wrapped - * nodes twice - */ - public Boolean hasChildren() { - return true; - } - - public Node getNode() { - return node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof NodesWrapper) - return node.equals(((NodesWrapper) obj).getNode()); - else - return false; - } - - public String toString() { - return "nodes wrapper based on " + node; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java deleted file mode 100644 index 934fa6781..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.query.Query; - -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** Content provider based on a JCR {@link Query}. */ -public class QueryTableContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 760371460907204722L; - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public Object[] getElements(Object inputElement) { - Query query = (Query) inputElement; - try { - NodeIterator nit = query.execute().getNodes(); - return JcrUtils.nodeIteratorToList(nit).toArray(); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/RowColumnLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/RowColumnLabelProvider.java deleted file mode 100644 index 70c71efea..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/RowColumnLabelProvider.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; - -/** Simplifies writing JCR-based column label provider. */ -public class RowColumnLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -6586692836928505358L; - - protected String getRowText(Row row) throws RepositoryException { - return super.getText(row); - } - - protected String getRowToolTipText(Row row) throws RepositoryException { - return super.getToolTipText(row); - } - - protected Image getRowImage(Row row) throws RepositoryException { - return super.getImage(row); - } - - protected Font getRowFont(Row row) throws RepositoryException { - return super.getFont(row); - } - - public Color getRowBackground(Row row) throws RepositoryException { - return super.getBackground(row); - } - - public Color getRowForeground(Row row) throws RepositoryException { - return super.getForeground(row); - } - - @Override - public String getText(Object element) { - try { - if (element instanceof Row) - return getRowText((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Row) - return getRowImage((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Row) - return getRowToolTipText((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Font getFont(Object element) { - try { - if (element instanceof Row) - return getRowFont((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getBackground(Object element) { - try { - if (element instanceof Row) - return getRowBackground((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getForeground(Object element) { - try { - if (element instanceof Row) - return getRowForeground((Row) element); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java deleted file mode 100644 index cb235d76b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.JcrUtils; - -/** Simple JCR node content provider taking a list of String as base path. */ -public class SimpleNodeContentProvider extends AbstractNodeContentProvider { - private static final long serialVersionUID = -8245193308831384269L; - private final List basePaths; - private Boolean mkdirs = false; - - public SimpleNodeContentProvider(Session session, String... basePaths) { - this(session, Arrays.asList(basePaths)); - } - - public SimpleNodeContentProvider(Session session, List basePaths) { - super(session); - this.basePaths = basePaths; - } - - @Override - protected Boolean isBasePath(String path) { - if (basePaths.contains(path)) - return true; - return super.isBasePath(path); - } - - public Object[] getElements(Object inputElement) { - try { - List baseNodes = new ArrayList(); - for (String basePath : basePaths) - if (mkdirs && !getSession().itemExists(basePath)) - baseNodes.add(JcrUtils.mkdirs(getSession(), basePath)); - else - baseNodes.add(getSession().getNode(basePath)); - return baseNodes.toArray(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get base nodes for " + basePaths, - e); - } - } - - public List getBasePaths() { - return basePaths; - } - - public void setMkdirs(Boolean mkdirs) { - this.mkdirs = mkdirs; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java deleted file mode 100644 index 1ce315429..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** Simplifies writing JCR-based column label provider. */ -public class VersionColumnLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -6117690082313161159L; - - protected String getVersionText(Version version) throws RepositoryException { - return super.getText(version); - } - - protected String getVersionToolTipText(Version version) throws RepositoryException { - return super.getToolTipText(version); - } - - protected Image getVersionImage(Version version) throws RepositoryException { - return super.getImage(version); - } - - protected String getUserName(Version version) throws RepositoryException { - Node node = version.getFrozenNode(); - if(node.hasProperty(Property.JCR_LAST_MODIFIED_BY)) - return node.getProperty(Property.JCR_LAST_MODIFIED_BY).getString(); - if(node.hasProperty(Property.JCR_CREATED_BY)) - return node.getProperty(Property.JCR_CREATED_BY).getString(); - return null; - } - -// protected String getActivityTitle(Version version) throws RepositoryException { -// Node activity = getActivity(version); -// if (activity == null) -// return null; -// if (activity.hasProperty("jcr:activityTitle")) -// return activity.getProperty("jcr:activityTitle").getString(); -// else -// return activity.getName(); -// } -// -// protected Node getActivity(Version version) throws RepositoryException { -// if (version.hasProperty(Property.JCR_ACTIVITY)) { -// return version.getProperty(Property.JCR_ACTIVITY).getNode(); -// } else -// return null; -// } - - @Override - public String getText(Object element) { - try { - return getVersionText((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - - @Override - public Image getImage(Object element) { - try { - return getVersionImage((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - - @Override - public String getToolTipText(Object element) { - try { - return getVersionToolTipText((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java deleted file mode 100644 index 32e5d30c1..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.version.VersionHistory; - -import org.argeo.jcr.Jcr; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** Content provider based on a {@link VersionHistory}. */ -public class VersionHistoryContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = -4921107883428887012L; - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public Object[] getElements(Object inputElement) { - VersionHistory versionHistory = (VersionHistory) inputElement; - return Jcr.getLinearVersions(versionHistory).toArray(); - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java deleted file mode 100644 index 43df1fe01..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; - -/** Wrap a node (created from a {@link NodesWrapper}) */ -public class WrappedNode { - private final NodesWrapper parent; - private final Node node; - - public WrappedNode(NodesWrapper parent, Node node) { - super(); - this.parent = parent; - this.node = node; - } - - public NodesWrapper getParent() { - return parent; - } - - public Node getNode() { - return node; - } - - public String toString() { - return "wrapped " + node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof WrappedNode) - return node.equals(((WrappedNode) obj).getNode()); - else - return false; - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java deleted file mode 100644 index c5dd73317..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.ColumnDefinition; - -/** - * Utility object to manage column in various tables and extracts displaying - * data from JCR - */ -public class JcrColumnDefinition extends ColumnDefinition { - private final static int DEFAULT_COLUMN_SIZE = 120; - - private String selectorName; - private String propertyName; - private int propertyType; - private int columnSize; - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Row} - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - */ - public JcrColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel) { - super(new SimpleJcrRowLabelProvider(selectorName, propertyName), - headerLabel); - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = DEFAULT_COLUMN_SIZE; - } - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Row} - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - * @param columnSize - */ - public JcrColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel, int columnSize) { - super(new SimpleJcrRowLabelProvider(selectorName, propertyName), - headerLabel, columnSize); - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = columnSize; - } - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Node} - * - * @param propertyName - * @param propertyType - * @param headerLabel - * @param columnSize - */ - public JcrColumnDefinition(String propertyName, int propertyType, - String headerLabel, int columnSize) { - super(new SimpleJcrNodeLabelProvider(propertyName), headerLabel, - columnSize); - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = columnSize; - } - - public String getSelectorName() { - return selectorName; - } - - public void setSelectorName(String selectorName) { - this.selectorName = selectorName; - } - - public String getPropertyName() { - return propertyName; - } - - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - public int getPropertyType() { - return propertyType; - } - - public void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - public int getColumnSize() { - return columnSize; - } - - public void setColumnSize(int columnSize) { - this.columnSize = columnSize; - } - - public String getHeaderLabel() { - return super.getLabel(); - } - - public void setHeaderLabel(String headerLabel) { - super.setLabel(headerLabel); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java deleted file mode 100644 index d9904605f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.math.BigDecimal; -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * Nodes. - * - * Note that the following snippet must be added before setting the comparator - * to the corresponding control: - * // IMPORTANT: initialize comparator before setting it - * JcrColumnDefinition firstCol = colDefs.get(0); - * comparator.setColumn(firstCol.getPropertyType(), - * firstCol.getPropertyName()); - * viewer.setComparator(comparator); - */ -public class NodeViewerComparator extends ViewerComparator { - private static final long serialVersionUID = -7782916140737279027L; - - protected String propertyName; - - protected int propertyType; - public static final int ASCENDING = 0, DESCENDING = 1; - protected int direction = DESCENDING; - - public NodeViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr nodes. - * - * @param viewer - * @param e1 - * @param e2 - * @return the comparison - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - int rc = 0; - long lc = 0; - - try { - Node n1 = (Node) e1; - Node n2 = (Node) e2; - - Value v1 = null; - Value v2 = null; - if (n1.hasProperty(propertyName)) - v1 = n1.getProperty(propertyName).getValue(); - if (n2.hasProperty(propertyName)) - v2 = n2.getProperty(propertyName).getValue(); - - if (v2 == null && v1 == null) - return 0; - else if (v2 == null) - return -1; - else if (v1 == null) - return 1; - - switch (propertyType) { - case PropertyType.STRING: - rc = v1.getString().compareTo(v2.getString()); - break; - case PropertyType.BOOLEAN: - boolean b1 = v1.getBoolean(); - boolean b2 = v2.getBoolean(); - if (b1 == b2) - rc = 0; - else - // we assume true is greater than false - rc = b1 ? 1 : -1; - break; - case PropertyType.DATE: - Calendar c1 = v1.getDate(); - Calendar c2 = v2.getDate(); - if (c1 == null || c2 == null) - // log.trace("undefined date"); - ; - lc = c1.getTimeInMillis() - c2.getTimeInMillis(); - if (lc < Integer.MIN_VALUE) - rc = -1; - else if (lc > Integer.MAX_VALUE) - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.LONG: - long l1; - long l2; - // TODO Sometimes an empty string is set instead of a long - try { - l1 = v1.getLong(); - } catch (ValueFormatException ve) { - l1 = 0; - } - try { - l2 = v2.getLong(); - } catch (ValueFormatException ve) { - l2 = 0; - } - - lc = l1 - l2; - if (lc < Integer.MIN_VALUE) - rc = -1; - else if (lc > Integer.MAX_VALUE) - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.DECIMAL: - BigDecimal bd1 = v1.getDecimal(); - BigDecimal bd2 = v2.getDecimal(); - rc = bd1.compareTo(bd2); - break; - case PropertyType.DOUBLE: - Double d1 = v1.getDouble(); - Double d2 = v2.getDouble(); - rc = d1.compareTo(d2); - break; - default: - throw new EclipseUiException( - "Unimplemented comparaison for PropertyType " - + propertyType); - } - // If descending order, flip the direction - if (direction == DESCENDING) { - rc = -rc; - } - - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error " - + "while comparing nodes", re); - } - return rc; - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String propertyName) { - if (this.propertyName != null && this.propertyName.equals(propertyName)) { - // Same column as last sort; toggle the direction - direction = 1 - direction; - } else { - // New column; do an ascending sort - this.propertyType = propertyType; - this.propertyName = propertyName; - direction = ASCENDING; - } - } - - // Getters and setters - protected String getPropertyName() { - return propertyName; - } - - protected void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - protected int getPropertyType() { - return propertyType; - } - - protected void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - protected int getDirection() { - return direction; - } - - protected void setDirection(int direction) { - this.direction = direction; - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java deleted file mode 100644 index 60d637d61..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.Viewer; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * rows - */ -public class RowViewerComparator extends NodeViewerComparator { - private static final long serialVersionUID = 7020939505172625113L; - protected String selectorName; - - public RowViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr rows. - * - * @param viewer - * @param e1 - * @param e2 - * @return the comparison - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - try { - Node n1 = ((Row) e1).getNode(selectorName); - Node n2 = ((Row) e2).getNode(selectorName); - return super.compare(viewer, n1, n2); - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error " - + "while comparing nodes", re); - } - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String selectorName, - String propertyName) { - if (this.selectorName != null && getPropertyName() != null - && this.selectorName.equals(selectorName) - && this.getPropertyName().equals(propertyName)) { - // Same column as last sort; toggle the direction - setDirection(1 - getDirection()); - } else { - // New column; do a descending sort - setPropertyType(propertyType); - setPropertyName(propertyName); - this.selectorName = selectorName; - setDirection(NodeViewerComparator.ASCENDING); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java deleted file mode 100644 index aa2e3375c..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; - -/** Base implementation of a label provider for controls that display JCR Nodes */ -public class SimpleJcrNodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -5215787695436221993L; - - private final static String DEFAULT_DATE_FORMAT = "EEE, dd MMM yyyy"; - private final static String DEFAULT_NUMBER_FORMAT = "#,##0.0"; - - private DateFormat dateFormat; - private NumberFormat numberFormat; - - final private String propertyName; - - /** - * Default Label provider for a given property of a node. Using default - * pattern for date and number formating - */ - public SimpleJcrNodeLabelProvider(String propertyName) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat).applyPattern(DEFAULT_NUMBER_FORMAT); - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrNodeLabelProvider(String propertyName, - String dateFormatPattern, String numberFormatPattern) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat( - dateFormatPattern == null ? DEFAULT_DATE_FORMAT - : dateFormatPattern); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat) - .applyPattern(numberFormatPattern == null ? DEFAULT_NUMBER_FORMAT - : numberFormatPattern); - } - - @Override - public String getText(Object element) { - try { - Node currNode = (Node) element; - - if (currNode.hasProperty(propertyName)) { - if (currNode.getProperty(propertyName).isMultiple()) { - StringBuilder builder = new StringBuilder(); - for (Value value : currNode.getProperty(propertyName) - .getValues()) { - String currStr = getSingleValueAsString(value); - if (notEmptyString(currStr)) - builder.append(currStr).append("; "); - } - if (builder.length() > 0) - builder.deleteCharAt(builder.length() - 2); - - return builder.toString(); - } else - return getSingleValueAsString(currNode.getProperty( - propertyName).getValue()); - } else - return ""; - } catch (RepositoryException re) { - throw new EclipseUiException("Unable to get text from row", re); - } - } - - private String getSingleValueAsString(Value value) - throws RepositoryException { - switch (value.getType()) { - case PropertyType.STRING: - return value.getString(); - case PropertyType.BOOLEAN: - return "" + value.getBoolean(); - case PropertyType.DATE: - return dateFormat.format(value.getDate().getTime()); - case PropertyType.LONG: - return "" + value.getLong(); - case PropertyType.DECIMAL: - return numberFormat.format(value.getDecimal()); - case PropertyType.DOUBLE: - return numberFormat.format(value.getDouble()); - case PropertyType.NAME: - return value.getString(); - default: - throw new EclipseUiException("Unimplemented label provider " - + "for property type " + value.getType() - + " while getting property " + propertyName + " - value: " - + value.getString()); - - } - } - - private boolean notEmptyString(String string) { - return string != null && !"".equals(string.trim()); - } - - public void setDateFormat(String dateFormatPattern) { - dateFormat = new SimpleDateFormat(dateFormatPattern); - } - - public void setNumberFormat(String numberFormatPattern) { - ((DecimalFormat) numberFormat).applyPattern(numberFormatPattern); - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java deleted file mode 100644 index 5d421f64b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** - * Base implementation of a label provider for widgets that display JCR Rows. - */ -public class SimpleJcrRowLabelProvider extends SimpleJcrNodeLabelProvider { - private static final long serialVersionUID = -3414654948197181740L; - - final private String selectorName; - - /** - * Default Label provider for a given property of a row. Using default - * pattern for date and number formating - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName) { - super(propertyName); - this.selectorName = selectorName; - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName, - String dateFormatPattern, String numberFormatPattern) { - super(propertyName, dateFormatPattern, numberFormatPattern); - this.selectorName = selectorName; - } - - @Override - public String getText(Object element) { - try { - Row currRow = (Row) element; - Node currNode = currRow.getNode(selectorName); - return super.getText(currNode); - } catch (RepositoryException re) { - throw new EclipseUiException("Unable to get Node " + selectorName - + " from row " + element, re); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java deleted file mode 100644 index 3678aab88..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR utilities for lists. */ -package org.argeo.eclipse.ui.jcr.lists; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/package-info.java deleted file mode 100644 index 19e3cc3ff..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR utilities. */ -package org.argeo.eclipse.ui.jcr; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java deleted file mode 100644 index c82e666d1..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Note that it might not be very - * reliable as long as we have not fixed login and multi repository issues that - * will be addressed in the next version. - * - * NOTE: id used here is the real id of the JCR Node, not the JCR Path - * - * Relies on common approach for JCR file handling implementation. - * - */ -@SuppressWarnings("deprecation") -public class JcrFileProvider implements FileProvider { - - // private Object[] rootNodes; - private Node refNode; - - /** - * Must be set in order for the provider to be able to get current session - * and thus have the ability to get the file node corresponding to a given - * file ID - * - * @param refNode - */ - public void setReferenceNode(Node refNode) { - // FIXME : this introduces some concurrency ISSUES. - this.refNode = refNode; - } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new EclipseUiException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot get stream from file node for Id " + fileId, re); - } - } - - /** - * Throws an exception if the node is not found in the current repository (a - * bit like a FileNotFoundException) - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = refNode.getSession().getNodeByIdentifier(fileId); - - // rootNodes: for (int j = 0; j < rootNodes.length; j++) { - // // in case we have a classic JCR Node - // if (rootNodes[j] instanceof Node) { - // Node curNode = (Node) rootNodes[j]; - // if (result != null) - // break rootNodes; - // } // Case of a repository Node - // else if (rootNodes[j] instanceof RepositoryNode) { - // Object[] nodes = ((RepositoryNode) rootNodes[j]) - // .getChildren(); - // for (int i = 0; i < nodes.length; i++) { - // Node node = (Node) nodes[i]; - // result = node.getSession().getNodeByIdentifier(fileId); - // if (result != null) - // break rootNodes; - // } - // } - // } - - // Sanity checks - if (result == null) - throw new EclipseUiException("File node not found for ID" + fileId); - - Node child = null; - - boolean isValid = true; - if (!result.isNodeType(NodeType.NT_FILE)) - // useless: mandatory child node - // || !result.hasNode(Property.JCR_CONTENT)) - isValid = false; - else { - child = result.getNode(Property.JCR_CONTENT); - if (!(child.isNodeType(NodeType.NT_RESOURCE) || child.hasProperty(Property.JCR_DATA))) - isValid = false; - } - - if (!isValid) - throw new EclipseUiException("ERROR: In the current implemented model, '" + NodeType.NT_FILE - + "' file node must have a child node named jcr:content " - + "that has a BINARY Property named jcr:data " + "where the actual data is stored"); - return child; - - } catch (RepositoryException re) { - throw new EclipseUiException("Erreur while getting file node of ID " + fileId, re); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java deleted file mode 100644 index fb123992f..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.util.Comparator; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** Compares two JCR items (node or properties) based on their names. */ -public class JcrItemsComparator implements Comparator { - public int compare(Item o1, Item o2) { - try { - // TODO: put folder before files - return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot compare " + o1 + " and " + o2, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java deleted file mode 100644 index 54b795f3b..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Compare JCR nodes based on their JCR identifiers, for use in JFace viewers. */ -public class NodeViewerComparer implements IElementComparer { - - // force comparison on Node IDs only. - public boolean equals(Object elementA, Object elementB) { - if (!(elementA instanceof Node) || !(elementB instanceof Node)) { - return elementA == null ? elementB == null : elementA - .equals(elementB); - } else { - - boolean result = false; - try { - String idA = ((Node) elementA).getIdentifier(); - String idB = ((Node) elementB).getIdentifier(); - result = idA == null ? idB == null : idA.equals(idB); - } catch (RepositoryException re) { - throw new EclipseUiException("cannot compare nodes", re); - } - - return result; - } - } - - public int hashCode(Object element) { - // TODO enhanced this method. - return element.getClass().toString().hashCode(); - } -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java deleted file mode 100644 index 291d579ac..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Unlike the - * JcrFileProvider , it relies on a single session and manages - * nodes with path only. - * - * Note that considered id is the JCR path - * - * Relies on common approach for JCR file handling implementation. - */ -@SuppressWarnings("deprecation") -public class SingleSessionFileProvider implements FileProvider { - - private Session session; - - public SingleSessionFileProvider(Session session) { - this.session = session; - } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new EclipseUiException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot get stream from file node for Id " - + fileId, re); - } - } - - /** - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = null; - result = session.getNode(fileId); - - // Sanity checks - if (result == null) - throw new EclipseUiException("File node not found for ID" + fileId); - - // Ensure that the node have the correct type. - if (!result.isNodeType(NodeType.NT_FILE)) - throw new EclipseUiException( - "Cannot open file children Node that are not of " - + NodeType.NT_RESOURCE + " type."); - - Node child = result.getNodes().nextNode(); - if (child == null || !child.isNodeType(NodeType.NT_RESOURCE)) - throw new EclipseUiException( - "ERROR: IN the current implemented model, " - + NodeType.NT_FILE - + " file node must have one and only one child of the nt:ressource, where actual data is stored"); - return child; - } catch (RepositoryException re) { - throw new EclipseUiException("Erreur while getting file node of ID " - + fileId, re); - } - } -} diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java deleted file mode 100644 index 016348cda..000000000 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR helpers. */ -package org.argeo.eclipse.ui.jcr.util; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/.classpath b/jcr/org.argeo.cms.jcr/.classpath deleted file mode 100644 index 3628e3368..000000000 --- a/jcr/org.argeo.cms.jcr/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/.project b/jcr/org.argeo.cms.jcr/.project deleted file mode 100644 index 3e470f829..000000000 --- a/jcr/org.argeo.cms.jcr/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - org.argeo.cms.jcr - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/jcr/org.argeo.cms.jcr/.settings/org.eclipse.jdt.core.prefs b/jcr/org.argeo.cms.jcr/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 7e2e11935..000000000 --- a/jcr/org.argeo.cms.jcr/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,101 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullable.secondary= -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/dataServletContext.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/dataServletContext.xml deleted file mode 100644 index f5fc8deaa..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/dataServletContext.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/filesServlet.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/filesServlet.xml deleted file mode 100644 index a283ef075..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/filesServlet.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/filesServletContext.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/filesServletContext.xml deleted file mode 100644 index 5fb56e3ed..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/filesServletContext.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrContentProvider.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/jcrContentProvider.xml deleted file mode 100644 index 47d724aea..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrContentProvider.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrDeployment.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/jcrDeployment.xml deleted file mode 100644 index 033ddbd2f..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrDeployment.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrFsProvider.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/jcrFsProvider.xml deleted file mode 100644 index e26453b06..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrFsProvider.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrRepositoryFactory.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/jcrRepositoryFactory.xml deleted file mode 100644 index b43b51920..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrRepositoryFactory.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrServletContext.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/jcrServletContext.xml deleted file mode 100644 index a0885bbc5..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/jcrServletContext.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/OSGI-INF/repositoryContextsFactory.xml b/jcr/org.argeo.cms.jcr/OSGI-INF/repositoryContextsFactory.xml deleted file mode 100644 index 2d06acad5..000000000 --- a/jcr/org.argeo.cms.jcr/OSGI-INF/repositoryContextsFactory.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/jcr/org.argeo.cms.jcr/bnd.bnd b/jcr/org.argeo.cms.jcr/bnd.bnd deleted file mode 100644 index 01446c1d0..000000000 --- a/jcr/org.argeo.cms.jcr/bnd.bnd +++ /dev/null @@ -1,40 +0,0 @@ -Bundle-Activator: org.argeo.cms.jcr.internal.osgi.CmsJcrActivator - -Provide-Capability:\ -cms.datamodel; name=jcrx; cnd=/org/argeo/jcr/jcrx.cnd; abstract=true,\ -cms.datamodel; name=argeo; cnd=/org/argeo/cms/jcr/argeo.cnd; abstract=true,\ -cms.datamodel;name=ldap; cnd=/org/argeo/cms/jcr/ldap.cnd; abstract=true,\ -osgi.service;objectClass="javax.jcr.Repository" - -Import-Package:\ -org.argeo.cms.servlet,\ -javax.jcr.security,\ -org.h2;resolution:=optional;version="[1,3)",\ -org.postgresql;version="[42,43)";resolution:=optional,\ -org.apache.commons.httpclient.cookie;resolution:=optional,\ -org.osgi.framework.namespace;version=0.0.0,\ -org.osgi.*;version=0.0.0,\ -org.osgi.service.http.whiteboard,\ -org.apache.jackrabbit.api.stats;version="[1,4)",\ -org.apache.jackrabbit.api;version="[1,4)",\ -org.apache.jackrabbit.commons;version="[1,4)",\ -org.apache.jackrabbit.spi;version="[1,4)",\ -org.apache.jackrabbit.spi2dav;version="[1,4)",\ -org.apache.jackrabbit.spi2davex;version="[1,4)",\ -org.apache.jackrabbit.webdav.jcr;version="[1,4)",\ -org.apache.jackrabbit.webdav.server;version="[1,4)",\ -org.apache.jackrabbit.webdav.simple;version="[1,4)",\ -org.apache.jackrabbit.*;version="[1,4)",\ -junit.*;resolution:=optional,\ -javax.servlet.*;version="[3,5)",\ -* - -Service-Component:\ -OSGI-INF/repositoryContextsFactory.xml,\ -OSGI-INF/jcrRepositoryFactory.xml,\ -OSGI-INF/jcrFsProvider.xml,\ -OSGI-INF/jcrDeployment.xml,\ -OSGI-INF/jcrServletContext.xml,\ -OSGI-INF/dataServletContext.xml,\ -OSGI-INF/filesServletContext.xml,\ -OSGI-INF/filesServlet.xml,\ diff --git a/jcr/org.argeo.cms.jcr/build.properties b/jcr/org.argeo.cms.jcr/build.properties deleted file mode 100644 index 859c241fe..000000000 --- a/jcr/org.argeo.cms.jcr/build.properties +++ /dev/null @@ -1,8 +0,0 @@ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - OSGI-INF/,\ - OSGI-INF/jcrContentProvider.xml -source.. = src/ -additional.bundles = org.apache.jackrabbit.data,\ - org.apache.jackrabbit.spi.commons diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/fs/CmsFsUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/fs/CmsFsUtils.java deleted file mode 100644 index 40d38eec2..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/fs/CmsFsUtils.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.argeo.cms.fs; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.FileSystem; -import java.nio.file.Path; -import java.nio.file.spi.FileSystemProvider; - -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.jcr.Jcr; - -/** Utilities around documents. */ -public class CmsFsUtils { - // TODO make it more robust and configurable - private static String baseWorkspaceName = CmsConstants.SYS_WORKSPACE; - - public static Node getNode(Repository repository, Path path) { - String workspaceName = path.getNameCount() == 0 ? baseWorkspaceName : path.getName(0).toString(); - String jcrPath = '/' + path.subpath(1, path.getNameCount()).toString(); - try { - Session newSession; - try { - newSession = repository.login(workspaceName); - } catch (NoSuchWorkspaceException e) { - // base workspace - newSession = repository.login(baseWorkspaceName); - jcrPath = path.toString(); - } - return newSession.getNode(jcrPath); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get node from path " + path, e); - } - } - - public static NodeIterator getLastUpdatedDocuments(Session session) { - try { - String qStr = "//element(*, nt:file)"; - qStr += " order by @jcr:lastModified descending"; - QueryManager queryManager = session.getWorkspace().getQueryManager(); - @SuppressWarnings("deprecation") - Query xpathQuery = queryManager.createQuery(qStr, Query.XPATH); - xpathQuery.setLimit(8); - NodeIterator nit = xpathQuery.execute().getNodes(); - return nit; - } catch (RepositoryException e) { - throw new IllegalStateException("Unable to retrieve last updated documents", e); - } - } - - public static Path getPath(FileSystemProvider nodeFileSystemProvider, URI uri) { - try { - FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri); - if (fileSystem == null) - fileSystem = nodeFileSystemProvider.newFileSystem(uri, null); - String path = uri.getPath(); - return fileSystem.getPath(path); - } catch (IOException e) { - throw new IllegalStateException("Unable to initialise file system for " + uri, e); - } - } - - public static Path getPath(FileSystemProvider nodeFileSystemProvider, Node node) { - String workspaceName = Jcr.getWorkspaceName(node); - String fullPath = baseWorkspaceName.equals(workspaceName) ? Jcr.getPath(node) - : '/' + workspaceName + Jcr.getPath(node); - URI uri; - try { - uri = new URI(CmsConstants.SCHEME_NODE, null, fullPath, null); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Cannot interpret " + fullPath + " as an URI", e); - } - return getPath(nodeFileSystemProvider, uri); - } - - /** Singleton. */ - private CmsFsUtils() { - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java deleted file mode 100644 index c2898577e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.argeo.cms.internal.jcr; - -import java.util.Properties; - -import org.apache.jackrabbit.core.config.BeanConfig; -import org.apache.jackrabbit.core.config.ConfigurationException; -import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; -import org.apache.jackrabbit.core.config.WorkspaceSecurityConfig; -import org.apache.jackrabbit.core.util.db.ConnectionFactory; -import org.w3c.dom.Element; - -/** - * A {@link RepositoryConfigurationParser} providing more flexibility with - * classloaders. - */ -@SuppressWarnings("restriction") -class CustomRepositoryConfigurationParser extends RepositoryConfigurationParser { - private ClassLoader classLoader = null; - - public CustomRepositoryConfigurationParser(Properties variables) { - super(variables); - } - - public CustomRepositoryConfigurationParser(Properties variables, ConnectionFactory connectionFactory) { - super(variables, connectionFactory); - } - - @Override - protected RepositoryConfigurationParser createSubParser(Properties variables) { - Properties props = new Properties(getVariables()); - props.putAll(variables); - CustomRepositoryConfigurationParser subParser = new CustomRepositoryConfigurationParser(props, - connectionFactory); - subParser.setClassLoader(classLoader); - return subParser; - } - - @Override - public WorkspaceSecurityConfig parseWorkspaceSecurityConfig(Element parent) throws ConfigurationException { - WorkspaceSecurityConfig workspaceSecurityConfig = super.parseWorkspaceSecurityConfig(parent); - workspaceSecurityConfig.getAccessControlProviderConfig().setClassLoader(classLoader); - return workspaceSecurityConfig; - } - - @Override - protected BeanConfig parseBeanConfig(Element parent, String name) throws ConfigurationException { - BeanConfig beanConfig = super.parseBeanConfig(parent, name); - if (beanConfig.getClassName().startsWith("org.argeo")) { - beanConfig.setClassLoader(classLoader); - } - return beanConfig; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JackrabbitType.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JackrabbitType.java deleted file mode 100644 index 40c83f6df..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JackrabbitType.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.argeo.cms.internal.jcr; - -/** Pre-defined Jackrabbit repository configurations. */ -enum JackrabbitType { - /** Local file system */ - localfs, - /** Embedded Java H2 database */ - h2, - /** Embedded Java H2 database in PostgreSQL compatibility mode */ - h2_postgresql, - /** PostgreSQL */ - postgresql, - /** PostgreSQL with datastore */ - postgresql_ds, - /** PostgreSQL with cluster */ - postgresql_cluster, - /** PostgreSQL with cluster and datastore */ - postgresql_cluster_ds, - /** Memory */ - memory; -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/LocalFsDataStore.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/LocalFsDataStore.java deleted file mode 100644 index dba005cb4..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/LocalFsDataStore.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.argeo.cms.internal.jcr; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; - -import org.apache.jackrabbit.core.data.DataIdentifier; -import org.apache.jackrabbit.core.data.DataRecord; -import org.apache.jackrabbit.core.data.DataStoreException; -import org.apache.jackrabbit.core.data.FileDataStore; - -/** - * experimental Duplicate added entries in another directory (typically a - * remote mount). - */ -@SuppressWarnings("restriction") -public class LocalFsDataStore extends FileDataStore { - String redundantPath; - FileDataStore redundantStore; - - @Override - public void init(String homeDir) { - // init primary first - super.init(homeDir); - - if (redundantPath != null) { - // redundant directory must be created first - // TODO implement some polling? - if (Files.exists(Paths.get(redundantPath))) { - redundantStore = new FileDataStore(); - redundantStore.setPath(redundantPath); - redundantStore.init(homeDir); - } - } - } - - @Override - public DataRecord addRecord(InputStream input) throws DataStoreException { - DataRecord dataRecord = super.addRecord(input); - syncRedundantRecord(dataRecord); - return dataRecord; - } - - @Override - public DataRecord getRecord(DataIdentifier identifier) throws DataStoreException { - DataRecord dataRecord = super.getRecord(identifier); - syncRedundantRecord(dataRecord); - return dataRecord; - } - - protected void syncRedundantRecord(DataRecord dataRecord) throws DataStoreException { - if (redundantStore == null) - return; - if (redundantStore.getRecordIfStored(dataRecord.getIdentifier()) == null) { - try (InputStream redundant = dataRecord.getStream()) { - redundantStore.addRecord(redundant); - } catch (IOException e) { - throw new DataStoreException("Cannot add redundant record.", e); - } - } - } - - public void setRedundantPath(String redundantPath) { - this.redundantPath = redundantPath; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java deleted file mode 100644 index 336ec8239..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.argeo.cms.internal.jcr; - -import org.argeo.api.cms.CmsConstants; - -/** JCR repository configuration */ -public enum RepoConf { - /** Repository type */ - type("h2"), - /** Default workspace */ - defaultWorkspace(CmsConstants.SYS_WORKSPACE), - /** Database URL */ - dburl(null), - /** Database user */ - dbuser(null), - /** Database password */ - dbpassword(null), - - /** The identifier (can be an URL locating the repo) */ - labeledUri(null), - // - // JACKRABBIT SPECIFIC - // - /** Maximum database pool size */ - maxPoolSize(10), - /** Maximum cache size in MB */ - maxCacheMB(null), - /** Bundle cache size in MB */ - bundleCacheMB(8), - /** Extractor pool size */ - extractorPoolSize(0), - /** Search cache size */ - searchCacheSize(1000), - /** Max volatile index size */ - maxVolatileIndexSize(1048576), - /** Cluster id (if appropriate configuration) */ - clusterId("default"), - /** Indexes base path */ - indexesBase(null); - - /** The default value. */ - private Object def; - - RepoConf(String oid, Object def) { - this.def = def; - } - - RepoConf(Object def) { - this.def = def; - } - - public Object getDefault() { - return def; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java deleted file mode 100644 index 3db97167c..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java +++ /dev/null @@ -1,225 +0,0 @@ -package org.argeo.cms.internal.jcr; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Dictionary; -import java.util.Enumeration; -import java.util.Properties; -import java.util.UUID; - -import javax.jcr.RepositoryException; - -import org.apache.jackrabbit.core.RepositoryContext; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.cache.CacheManager; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.jcr.internal.CmsPaths; -import org.xml.sax.InputSource; - -/** Can interpret properties in order to create an actual JCR repository. */ -public class RepositoryBuilder { - private final static CmsLog log = CmsLog.getLog(RepositoryBuilder.class); - - public RepositoryContext createRepositoryContext(Dictionary properties) - throws RepositoryException, IOException { - RepositoryConfig repositoryConfig = createRepositoryConfig(properties); - RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig); - RepositoryImpl repository = repositoryContext.getRepository(); - - // cache - Object maxCacheMbStr = prop(properties, RepoConf.maxCacheMB); - if (maxCacheMbStr != null) { - Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString()); - CacheManager cacheManager = repository.getCacheManager(); - cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l); - cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l); - } - - return repositoryContext; - } - - RepositoryConfig createRepositoryConfig(Dictionary properties) throws RepositoryException, IOException { - JackrabbitType type = JackrabbitType.valueOf(prop(properties, RepoConf.type).toString()); - ClassLoader cl = getClass().getClassLoader(); - final String base = "/org/argeo/cms/internal/jcr"; - try (InputStream in = cl.getResourceAsStream(base + "/repository-" + type.name() + ".xml")) { - if (in == null) - throw new IllegalArgumentException("Repository configuration not found"); - InputSource config = new InputSource(in); - Properties jackrabbitVars = getConfigurationProperties(type, properties); - // RepositoryConfig repositoryConfig = RepositoryConfig.create(config, - // jackrabbitVars); - - // custom configuration parser - CustomRepositoryConfigurationParser parser = new CustomRepositoryConfigurationParser(jackrabbitVars); - parser.setClassLoader(cl); - RepositoryConfig repositoryConfig = parser.parseRepositoryConfig(config); - repositoryConfig.init(); - - // set the proper classloaders - repositoryConfig.getSecurityConfig().getSecurityManagerConfig().setClassLoader(cl); - repositoryConfig.getSecurityConfig().getAccessManagerConfig().setClassLoader(cl); -// for (WorkspaceConfig workspaceConfig : repositoryConfig.getWorkspaceConfigs()) { -// workspaceConfig.getSecurityConfig().getAccessControlProviderConfig().setClassLoader(cl); -// } - return repositoryConfig; - } - } - - private Properties getConfigurationProperties(JackrabbitType type, Dictionary properties) { - Properties props = new Properties(); - for (Enumeration keys = properties.keys(); keys.hasMoreElements();) { - String key = keys.nextElement(); - props.put(key, properties.get(key)); - } - - // cluster id - // cf. https://wiki.apache.org/jackrabbit/Clustering - // TODO deal with multiple repos - String clusterId = System.getProperty("org.apache.jackrabbit.core.cluster.node_id"); - String clusterIdProp = props.getProperty(RepoConf.clusterId.name()); - if (clusterId != null) { - if (clusterIdProp != null) - throw new IllegalArgumentException("Cluster id defined as System properties and in deploy config"); - props.put(RepoConf.clusterId.name(), clusterId); - } else { - clusterId = clusterIdProp; - } - - // home - String homeUri = props.getProperty(RepoConf.labeledUri.name()); - Path homePath; - if (homeUri == null) { - String cn = props.getProperty(CmsConstants.CN); - assert cn != null; - if (clusterId != null) { - homePath = CmsPaths.getRepoDirPath(cn + '/' + clusterId); - } else { - homePath = CmsPaths.getRepoDirPath(cn); - } - } else { - try { - URI uri = new URI(homeUri); - String host = uri.getHost(); - if (host == null || host.trim().equals("")) { - homePath = Paths.get(uri).toAbsolutePath(); - } else { - // TODO remote at this stage? - throw new IllegalArgumentException("Cannot manage repository path for host " + host); - } - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid repository home URI", e); - } - } - // TODO use Jackrabbit API (?) - Path rootUuidPath = homePath.resolve("repository/meta/rootUUID"); - try { - if (!Files.exists(rootUuidPath)) { - Files.createDirectories(rootUuidPath.getParent()); - Files.write(rootUuidPath, UUID.randomUUID().toString().getBytes()); - } - // File homeDir = homePath.toFile(); - // homeDir.mkdirs(); - } catch (IOException e) { - throw new RuntimeException("Cannot set up repository home " + homePath, e); - } - // home cannot be overridden - props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString()); - - setProp(props, RepoConf.indexesBase, CmsPaths.getRepoIndexesBase().toString()); - // common - setProp(props, RepoConf.defaultWorkspace); - setProp(props, RepoConf.maxPoolSize); - // Jackrabbit defaults - setProp(props, RepoConf.bundleCacheMB); - // See http://wiki.apache.org/jackrabbit/Search - setProp(props, RepoConf.extractorPoolSize); - setProp(props, RepoConf.searchCacheSize); - setProp(props, RepoConf.maxVolatileIndexSize); - - // specific - String dburl; - switch (type) { - case h2: - dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository"; - setProp(props, RepoConf.dburl, dburl); - setProp(props, RepoConf.dbuser, "sa"); - setProp(props, RepoConf.dbpassword, ""); - break; - case h2_postgresql: - dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE"; - setProp(props, RepoConf.dburl, dburl); - setProp(props, RepoConf.dbuser, "sa"); - setProp(props, RepoConf.dbpassword, ""); - break; - case postgresql: - case postgresql_ds: - case postgresql_cluster: - case postgresql_cluster_ds: - dburl = "jdbc:postgresql://localhost/demo"; - setProp(props, RepoConf.dburl, dburl); - setProp(props, RepoConf.dbuser, "argeo"); - setProp(props, RepoConf.dbpassword, "argeo"); - break; - case memory: - break; - case localfs: - break; - default: - throw new IllegalArgumentException("Unsupported node type " + type); - } - return props; - } - - private void setProp(Properties props, RepoConf key, String def) { - Object value = props.get(key.name()); - if (value == null) - value = def; - if (value == null) - value = key.getDefault(); - if (value != null) - props.put(key.name(), value.toString()); - } - - private void setProp(Properties props, RepoConf key) { - setProp(props, key, null); - } - - private String prop(Dictionary properties, RepoConf key) { - Object value = properties.get(key.name()); - if (value == null) - return key.getDefault() != null ? key.getDefault().toString() : null; - else - return value.toString(); - } - - private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException { - ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(RepositoryBuilder.class.getClassLoader()); - try { - long begin = System.currentTimeMillis(); - // - // Actual repository creation - // - RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig); - - double duration = ((double) (System.currentTimeMillis() - begin)) / 1000; - if (log.isDebugEnabled()) - log.debug( - "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir()); - - return repositoryContext; - } finally { - Thread.currentThread().setContextClassLoader(currentContextCl); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2.xml deleted file mode 100644 index ace0fa5ee..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2_postgresql.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2_postgresql.xml deleted file mode 100644 index 430367656..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-h2_postgresql.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-localfs.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-localfs.xml deleted file mode 100644 index b88907919..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-localfs.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-memory.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-memory.xml deleted file mode 100644 index 3630a149d..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-memory.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql.xml deleted file mode 100644 index de2f245ad..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster.xml deleted file mode 100644 index 488ad6b72..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster_ds.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster_ds.xml deleted file mode 100644 index b430674c9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_cluster_ds.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_ds.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_ds.xml deleted file mode 100644 index 5229d1660..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/repository-postgresql_ds.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java deleted file mode 100644 index 7fde17751..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/CmsJcrUtils.java +++ /dev/null @@ -1,278 +0,0 @@ -package org.argeo.cms.jcr; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; -import javax.security.auth.AuthPermission; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -import org.argeo.api.cms.CmsAuth; -import org.argeo.api.cms.CmsConstants; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.CurrentSubject; - -/** Utilities related to Argeo model in JCR */ -public class CmsJcrUtils { - /** - * Wraps the call to the repository factory based on parameter - * {@link CmsConstants#CN} in order to simplify it and protect against future - * API changes. - */ - public static Repository getRepositoryByAlias(RepositoryFactory repositoryFactory, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(CmsConstants.CN, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias, - e); - } - } - - /** - * Wraps the call to the repository factory based on parameter - * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against - * future API changes. - */ - public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri) { - return getRepositoryByUri(repositoryFactory, uri, null); - } - - /** - * Wraps the call to the repository factory based on parameter - * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against - * future API changes. - */ - public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri, String alias) { - try { - Map parameters = new HashMap(); - parameters.put(CmsConstants.LABELED_URI, uri); - if (alias != null) - parameters.put(CmsConstants.CN, alias); - return repositoryFactory.getRepository(parameters); - } catch (RepositoryException e) { - throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri, e); - } - } - - /** - * Returns the home node of the user or null if none was found. - * - * @param session the session to use in order to perform the search, this can - * be a session with a different user ID than the one searched, - * typically when a system or admin session is used. - * @param username the username of the user - */ - public static Node getUserHome(Session session, String username) { -// try { -// QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory(); -// Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel"); -// DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID); -// StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username)); -// Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop); -// Query query = qomf.createQuery(sel, constraint, null, null); -// return querySingleNode(query); -// } catch (RepositoryException e) { -// throw new RuntimeException("Cannot find home for user " + username, e); -// } - - try { - checkUserWorkspace(session, username); - String homePath = getHomePath(username); - if (session.itemExists(homePath)) - return session.getNode(homePath); - // legacy - homePath = "/home/" + username; - if (session.itemExists(homePath)) - return session.getNode(homePath); - return null; - } catch (RepositoryException e) { - throw new RuntimeException("Cannot find home for user " + username, e); - } - } - - private static String getHomePath(String username) { - LdapName dn; - try { - dn = new LdapName(username); - } catch (InvalidNameException e) { - throw new IllegalArgumentException("Invalid name " + username, e); - } - String userId = dn.getRdn(dn.size() - 1).getValue().toString(); - return '/' + userId; - } - - private static void checkUserWorkspace(Session session, String username) { - String workspaceName = session.getWorkspace().getName(); - if (!CmsConstants.HOME_WORKSPACE.equals(workspaceName)) - throw new IllegalArgumentException(workspaceName + " is not the home workspace for user " + username); - } - - /** - * Returns the home node of the user or null if none was found. - * - * @param session the session to use in order to perform the search, this can - * be a session with a different user ID than the one searched, - * typically when a system or admin session is used. - * @param groupname the name of the group - */ - public static Node getGroupHome(Session session, String groupname) { -// try { -// QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory(); -// Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel"); -// DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN); -// StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn)); -// Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop); -// Query query = qomf.createQuery(sel, constraint, null, null); -// return querySingleNode(query); -// } catch (RepositoryException e) { -// throw new RuntimeException("Cannot find home for group " + cn, e); -// } - - try { - checkGroupWorkspace(session, groupname); - String homePath = getGroupPath(groupname); - if (session.itemExists(homePath)) - return session.getNode(homePath); - // legacy - homePath = "/groups/" + groupname; - if (session.itemExists(homePath)) - return session.getNode(homePath); - return null; - } catch (RepositoryException e) { - throw new RuntimeException("Cannot find home for group " + groupname, e); - } - - } - - private static String getGroupPath(String groupname) { - String cn; - try { - LdapName dn = new LdapName(groupname); - cn = dn.getRdn(dn.size() - 1).getValue().toString(); - } catch (InvalidNameException e) { - cn = groupname; - } - return '/' + cn; - } - - private static void checkGroupWorkspace(Session session, String groupname) { - String workspaceName = session.getWorkspace().getName(); - if (!CmsConstants.SRV_WORKSPACE.equals(workspaceName)) - throw new IllegalArgumentException(workspaceName + " is not the group workspace for group " + groupname); - } - - /** - * Queries one single node. - * - * @return one single node or null if none was found - * @throws ArgeoJcrException if more than one node was found - */ -// private static Node querySingleNode(Query query) { -// NodeIterator nodeIterator; -// try { -// QueryResult queryResult = query.execute(); -// nodeIterator = queryResult.getNodes(); -// } catch (RepositoryException e) { -// throw new RuntimeException("Cannot execute query " + query, e); -// } -// Node node; -// if (nodeIterator.hasNext()) -// node = nodeIterator.nextNode(); -// else -// return null; -// -// if (nodeIterator.hasNext()) -// throw new RuntimeException("Query returned more than one node."); -// return node; -// } - - /** Returns the home node of the session user or null if none was found. */ - public static Node getUserHome(Session session) { - String userID = session.getUserID(); - return getUserHome(session, userID); - } - - /** Whether this node is the home of the user of the underlying session. */ - public static boolean isUserHome(Node node) { - try { - String userID = node.getSession().getUserID(); - return node.hasProperty(Property.JCR_ID) && node.getProperty(Property.JCR_ID).getString().equals(userID); - } catch (RepositoryException e) { - throw new IllegalStateException(e); - } - } - - /** - * Translate the path to this node into a path containing the name of the - * repository and the name of the workspace. - */ - public static String getDataPath(String cn, Node node) { - assert node != null; - StringBuilder buf = new StringBuilder(CmsConstants.PATH_DATA); - try { - return buf.append('/').append(cn).append('/').append(node.getSession().getWorkspace().getName()) - .append(node.getPath()).toString(); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get data path for " + node + " in repository " + cn, e); - } - } - - /** - * Translate the path to this node into a path containing the name of the - * repository and the name of the workspace. - */ - public static String getDataPath(Node node) { - return getDataPath(CmsConstants.NODE, node); - } - - /** - * Open a JCR session with full read/write rights on the data, as - * {@link CmsConstants#ROLE_USER_ADMIN}, using the - * {@link CmsAuth#LOGIN_CONTEXT_DATA_ADMIN} login context. For security hardened - * deployement, use {@link AuthPermission} on this login context. - */ - public static Session openDataAdminSession(Repository repository, String workspaceName) { - LoginContext loginContext; - try { - loginContext = CmsAuth.DATA_ADMIN.newLoginContext(); - loginContext.login(); - } catch (LoginException e1) { - throw new RuntimeException("Could not login as data admin", e1); - } finally { - } - - ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(CmsJcrUtils.class.getClassLoader()); - return CurrentSubject.callAs(loginContext.getSubject(), () -> { - try { - return JcrUtils.loginOrCreateWorkspace(repository, workspaceName); - } catch (NoSuchWorkspaceException e) {// should not happen - throw new IllegalArgumentException("No workspace " + workspaceName + " available", e); - } catch (RepositoryException e) { - throw new RuntimeException("Cannot open data admin session", e); - } - } - - ); - } finally { - Thread.currentThread().setContextClassLoader(currentCl); - } - } - - /** Singleton. */ - private CmsJcrUtils() { - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContent.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContent.java deleted file mode 100644 index a4af35bc6..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContent.java +++ /dev/null @@ -1,387 +0,0 @@ -package org.argeo.cms.jcr.acr; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ForkJoinPool; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; -import javax.xml.namespace.QName; -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; - -import org.argeo.api.acr.Content; -import org.argeo.api.acr.NamespaceUtils; -import org.argeo.api.acr.spi.ContentProvider; -import org.argeo.api.acr.spi.ProvidedSession; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.acr.AbstractContent; -import org.argeo.cms.acr.ContentUtils; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** A JCR {@link Node} accessed as {@link Content}. */ -public class JcrContent extends AbstractContent { -// private Node jcrNode; - - private JcrContentProvider provider; - - private String jcrWorkspace; - private String jcrPath; - - protected JcrContent(ProvidedSession session, JcrContentProvider provider, String jcrWorkspace, String jcrPath) { - super(session); - this.provider = provider; - this.jcrWorkspace = jcrWorkspace; - this.jcrPath = jcrPath; - } - - @Override - public QName getName() { - String name = Jcr.getName(getJcrNode()); - if (name.equals("")) {// root - String mountPath = provider.getMountPath(); - name = ContentUtils.getParentPath(mountPath)[1]; - // name = Jcr.getWorkspaceName(getJcrNode()); - } - return NamespaceUtils.parsePrefixedName(provider, name); - } - - @SuppressWarnings("unchecked") - @Override - public Optional get(QName key, Class clss) { - if (isDefaultAttrTypeRequested(clss)) { - return Optional.of((A) get(getJcrNode(), key.toString())); - } - return Optional.of((A) Jcr.get(getJcrNode(), key.toString())); - } - - @Override - public Iterator iterator() { - try { - return new JcrContentIterator(getJcrNode().getNodes()); - } catch (RepositoryException e) { - throw new JcrException("Cannot list children of " + getJcrNode(), e); - } - } - - @Override - protected Iterable keys() { - try { - Set keys = new HashSet<>(); - for (PropertyIterator propertyIterator = getJcrNode().getProperties(); propertyIterator.hasNext();) { - Property property = propertyIterator.nextProperty(); - // TODO convert standard names - // TODO skip technical properties - QName name = NamespaceUtils.parsePrefixedName(provider, property.getName()); - keys.add(name); - } - return keys; - } catch (RepositoryException e) { - throw new JcrException("Cannot list properties of " + getJcrNode(), e); - } - } - - public Node getJcrNode() { - try { - // TODO caching? - return provider.getJcrSession(getSession(), jcrWorkspace).getNode(jcrPath); - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve " + jcrPath + " from workspace " + jcrWorkspace, e); - } - } - - /** Cast to a standard Java object. */ - static Object get(Node node, String property) { - try { - Property p = node.getProperty(property); - if (p.isMultiple()) { - Value[] values = p.getValues(); - List lst = new ArrayList<>(); - for (Value value : values) { - lst.add(convertSingleValue(value)); - } - return lst; - } else { - Value value = node.getProperty(property).getValue(); - return convertSingleValue(value); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot cast value from " + property + " of node " + node, e); - } - } - - static Object convertSingleValue(Value value) throws RepositoryException { - switch (value.getType()) { - case PropertyType.STRING: - return value.getString(); - case PropertyType.DOUBLE: - return (Double) value.getDouble(); - case PropertyType.LONG: - return (Long) value.getLong(); - case PropertyType.BOOLEAN: - return (Boolean) value.getBoolean(); - case PropertyType.DATE: - Calendar calendar = value.getDate(); - return calendar.toInstant(); - case PropertyType.BINARY: - throw new IllegalArgumentException("Binary is not supported as an attribute"); - default: - return value.getString(); - } - } - - class JcrContentIterator implements Iterator { - private final NodeIterator nodeIterator; - // we keep track in order to be able to delete it - private JcrContent current = null; - - protected JcrContentIterator(NodeIterator nodeIterator) { - this.nodeIterator = nodeIterator; - } - - @Override - public boolean hasNext() { - return nodeIterator.hasNext(); - } - - @Override - public Content next() { - current = new JcrContent(getSession(), provider, jcrWorkspace, Jcr.getPath(nodeIterator.nextNode())); - return current; - } - - @Override - public void remove() { - if (current != null) { - Jcr.remove(current.getJcrNode()); - } - } - - } - - @Override - public String getPath() { - try { - // Note: it is important to to use the default way (recursing through parents), - // since the session may not have access to parent nodes - return ContentUtils.ROOT_SLASH + jcrWorkspace + getJcrNode().getPath(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get depth of " + getJcrNode(), e); - } - } - - @Override - public int getDepth() { - try { - return getJcrNode().getDepth() + 1; - } catch (RepositoryException e) { - throw new JcrException("Cannot get depth of " + getJcrNode(), e); - } - } - - @Override - public Content getParent() { - if (Jcr.isRoot(getJcrNode())) // root - return null; - return new JcrContent(getSession(), provider, jcrWorkspace, Jcr.getParentPath(getJcrNode())); - } - - @Override - public Content add(QName name, QName... classes) { - if (classes.length > 0) { - QName primaryType = classes[0]; - Node child = Jcr.addNode(getJcrNode(), name.toString(), primaryType.toString()); - for (int i = 1; i < classes.length; i++) { - try { - child.addMixin(classes[i].toString()); - } catch (RepositoryException e) { - throw new JcrException("Cannot add child to " + getJcrNode(), e); - } - } - - } else { - Jcr.addNode(getJcrNode(), name.toString(), NodeType.NT_UNSTRUCTURED); - } - return null; - } - - @Override - public void remove() { - Jcr.remove(getJcrNode()); - } - - @Override - protected void removeAttr(QName key) { - Property property = Jcr.getProperty(getJcrNode(), key.toString()); - if (property != null) { - try { - property.remove(); - } catch (RepositoryException e) { - throw new JcrException("Cannot remove property " + key + " from " + getJcrNode(), e); - } - } - - } - - boolean exists() { - try { - return provider.getJcrSession(getSession(), jcrWorkspace).itemExists(jcrPath); - } catch (RepositoryException e) { - throw new JcrException("Cannot check whether " + jcrPath + " exists", e); - } - } - - /* - * ADAPTERS - */ - @SuppressWarnings("unchecked") - public A adapt(Class clss) { - if (Source.class.isAssignableFrom(clss)) { -// try { - PipedInputStream in = new PipedInputStream(); - - ForkJoinPool.commonPool().execute(() -> { - try (PipedOutputStream out = new PipedOutputStream(in)) { - provider.getJcrSession(getSession(), jcrWorkspace).exportDocumentView(jcrPath, out, true, false); - out.flush(); - } catch (IOException | RepositoryException e) { - throw new RuntimeException("Cannot export " + jcrPath + " in workspace " + jcrWorkspace, e); - } - - }); - return (A) new StreamSource(in); -// } catch (IOException e) { -// throw new RuntimeException("Cannot adapt " + JcrContent.this + " to " + clss, e); -// } - } else - - return super.adapt(clss); - } - - @SuppressWarnings("unchecked") - @Override - public C open(Class clss) throws IOException, IllegalArgumentException { - if (InputStream.class.isAssignableFrom(clss)) { - Node node = getJcrNode(); - if (Jcr.isNodeType(node, NodeType.NT_FILE)) { - try { - return (C) JcrUtils.getFileAsStream(node); - } catch (RepositoryException e) { - throw new JcrException("Cannot open " + jcrPath + " in workspace " + jcrWorkspace, e); - } - } - } - return super.open(clss); - } - - @Override - public ContentProvider getProvider() { - return provider; - } - - @Override - public String getSessionLocalId() { - try { - return getJcrNode().getIdentifier(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get identifier for " + getJcrNode(), e); - } - } - - /* - * TYPING - */ - @Override - public List getContentClasses() { - try { -// Node node = getJcrNode(); -// List res = new ArrayList<>(); -// res.add(nodeTypeToQName(node.getPrimaryNodeType())); -// for (NodeType mixin : node.getMixinNodeTypes()) { -// res.add(nodeTypeToQName(mixin)); -// } -// return res; - Node context = getJcrNode(); - - List res = new ArrayList<>(); - // primary node type - NodeType primaryType = context.getPrimaryNodeType(); - res.add(nodeTypeToQName(primaryType)); - - Set secondaryTypes = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR); - for (NodeType mixinType : context.getMixinNodeTypes()) { - secondaryTypes.add(nodeTypeToQName(mixinType)); - } - for (NodeType superType : primaryType.getDeclaredSupertypes()) { - secondaryTypes.add(nodeTypeToQName(superType)); - } - // mixins - for (NodeType mixinType : context.getMixinNodeTypes()) { - for (NodeType superType : mixinType.getDeclaredSupertypes()) { - secondaryTypes.add(nodeTypeToQName(superType)); - } - } -// // entity type -// if (context.isNodeType(EntityType.entity.get())) { -// if (context.hasProperty(EntityNames.ENTITY_TYPE)) { -// String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString(); -// if (byType.containsKey(entityTypeName)) { -// types.add(entityTypeName); -// } -// } -// } - res.addAll(secondaryTypes); - return res; - } catch (RepositoryException e) { - throw new JcrException("Cannot list node types from " + getJcrNode(), e); - } - } - - private QName nodeTypeToQName(NodeType nodeType) { - String name = nodeType.getName(); - return QName.valueOf(name); - } - - @Override - public int getSiblingIndex() { - return Jcr.getIndex(getJcrNode()); - } - - /* - * STATIC UTLITIES - */ - public static Content nodeToContent(Node node) { - if (node == null) - return null; - try { - ProvidedSession contentSession = (ProvidedSession) node.getSession() - .getAttribute(ProvidedSession.class.getName()); - if (contentSession == null) - throw new IllegalArgumentException( - "Cannot adapt " + node + " to content, because it was not loaded from a content session"); - return contentSession.get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot adapt " + node + " to a content", e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentProvider.java deleted file mode 100644 index eaa27b7fc..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentProvider.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.argeo.cms.jcr.acr; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.xml.namespace.NamespaceContext; - -import org.argeo.api.acr.Content; -import org.argeo.api.acr.spi.ContentProvider; -import org.argeo.api.acr.spi.ProvidedContent; -import org.argeo.api.acr.spi.ProvidedSession; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.acr.ContentUtils; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** A JCR workspace accessed as an {@link ContentProvider}. */ -public class JcrContentProvider implements ContentProvider, NamespaceContext { - - private Repository jcrRepository; - private Session adminSession; - - private String mountPath; - - // cache - private String jcrWorkspace; - - private Map sessionAdapters = Collections.synchronizedMap(new HashMap<>()); - - public void start(Map properties) { - mountPath = properties.get(CmsConstants.ACR_MOUNT_PATH); - if ("/".equals(mountPath)) - throw new IllegalArgumentException("JCR content provider cannot be root /"); - Objects.requireNonNull(mountPath); - jcrWorkspace = ContentUtils.getParentPath(mountPath)[1]; - adminSession = CmsJcrUtils.openDataAdminSession(jcrRepository, jcrWorkspace); - } - - public void stop() { - if (adminSession.isLive()) - JcrUtils.logoutQuietly(adminSession); - } - - public void setJcrRepository(Repository jcrRepository) { - this.jcrRepository = jcrRepository; - } - - @Override - public ProvidedContent get(ProvidedSession contentSession, String relativePath) { - String jcrPath = "/" + relativePath; - return new JcrContent(contentSession, this, jcrWorkspace, jcrPath); - } - - @Override - public boolean exists(ProvidedSession contentSession, String relativePath) { - String jcrWorkspace = ContentUtils.getParentPath(mountPath)[1]; - String jcrPath = "/" + relativePath; - return new JcrContent(contentSession, this, jcrWorkspace, jcrPath).exists(); - } - - public Session getJcrSession(ProvidedSession contentSession, String jcrWorkspace) { - JcrSessionAdapter sessionAdapter = sessionAdapters.get(contentSession); - if (sessionAdapter == null) { - final JcrSessionAdapter newSessionAdapter = new JcrSessionAdapter(jcrRepository, contentSession, - contentSession.getSubject()); - sessionAdapters.put(contentSession, newSessionAdapter); - contentSession.onClose().thenAccept((s) -> newSessionAdapter.close()); - sessionAdapter = newSessionAdapter; - } - - Session jcrSession = sessionAdapter.getSession(jcrWorkspace); - return jcrSession; - } - - public Session getJcrSession(Content content, String jcrWorkspace) { - return getJcrSession(((ProvidedContent) content).getSession(), jcrWorkspace); - } - - @Override - public String getMountPath() { - return mountPath; - } - - /* - * NAMESPACE CONTEXT - */ - @Override - public String getNamespaceURI(String prefix) { - try { - return adminSession.getNamespaceURI(prefix); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - @Override - public String getPrefix(String namespaceURI) { - try { - return adminSession.getNamespacePrefix(namespaceURI); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - @Override - public Iterator getPrefixes(String namespaceURI) { - try { - return Arrays.asList(adminSession.getNamespacePrefix(namespaceURI)).iterator(); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentUtils.java deleted file mode 100644 index 25e54b302..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContentUtils.java +++ /dev/null @@ -1,261 +0,0 @@ -package org.argeo.cms.jcr.acr; - -import java.io.IOException; -import java.io.InputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Source; -import javax.xml.transform.dom.DOMSource; - -import org.argeo.api.acr.Content; -import org.argeo.api.acr.ContentName; -import org.argeo.api.acr.CrName; -import org.argeo.api.acr.DName; -import org.argeo.api.acr.NamespaceUtils; -import org.argeo.api.acr.spi.ProvidedContent; -import org.argeo.api.acr.spi.ProvidedSession; -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** Utilities around integration between JCR and ACR. */ -public class JcrContentUtils { - private final static CmsLog log = CmsLog.getLog(JcrContentUtils.class); - - public static void copyFiles(Node folder, Content collection, String... additionalCollectionTypes) { - try { - log.debug("Copy collection " + collection); - - NamespaceContext jcrNamespaceContext = new JcrSessionNamespaceContext(folder.getSession()); - - nodes: for (NodeIterator it = folder.getNodes(); it.hasNext();) { - Node node = it.nextNode(); - String name = node.getName(); - if (node.isNodeType(NodeType.NT_FILE)) { - Content file = collection.anyOrAddChild(new ContentName(name)); - try (InputStream in = JcrUtils.getFileAsStream(node)) { - file.write(InputStream.class).complete(in); - } - } else if (node.isNodeType(NodeType.NT_FOLDER)) { - Content subCol = collection.add(name, DName.collection.qName()); - copyFiles(node, subCol, additionalCollectionTypes); - } else { - List contentClasses = typesAsContentClasses(node, jcrNamespaceContext); - for (String collectionType : additionalCollectionTypes) { - if (node.isNodeType(collectionType)) { - contentClasses.add(DName.collection.qName()); - Content subCol = collection.add(name, - contentClasses.toArray(new QName[contentClasses.size()])); - setAttributes(node, subCol, jcrNamespaceContext); -// setContentClasses(node, subCol, jcrNamespaceContext); - copyFiles(node, subCol, additionalCollectionTypes); - continue nodes; - } - } - - QName qName = NamespaceUtils.parsePrefixedName(name); -// if (NamespaceUtils.hasNamespace(qName)) { - if (node.getIndex() > 1) { - log.warn("Same name siblings not supported, skipping " + node); - continue nodes; - } - Content content = collection.add(qName, contentClasses.toArray(new QName[contentClasses.size()])); - Source source = toSource(node); - ((ProvidedContent) content).getSession().edit((s) -> { - ((ProvidedSession) s).notifyModification((ProvidedContent) content); - content.write(Source.class).complete(source); -// try { -// //setContentClasses(node, content, jcrNamespaceContext); -// } catch (RepositoryException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } - }).toCompletableFuture().join(); - setAttributes(node, content, jcrNamespaceContext); - -// } else { -// // ignore -// log.debug(() -> "Ignored " + node); -// continue nodes; -// } - } - } - } catch (RepositoryException e) { - throw new JcrException("Cannot copy files from " + folder + " to " + collection, e); - } catch (IOException e) { - throw new RuntimeException("Cannot copy files from " + folder + " to " + collection, e); - } - } - - private static Source toSource(Node node) throws RepositoryException { - -// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { -// node.getSession().exportDocumentView(node.getPath(), out, true, false); -// System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8)); -//// DocumentBuilder documentBuilder = DocumentBuilderFactory.newNSInstance().newDocumentBuilder(); -//// Document document; -//// try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())) { -//// document = documentBuilder.parse(in); -//// } -//// cleanJcrDom(document); -//// return new DOMSource(document); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } - - try (PipedInputStream in = new PipedInputStream();) { - - CompletableFuture toDo = CompletableFuture.supplyAsync(() -> { - try { - DocumentBuilder documentBuilder = DocumentBuilderFactory.newNSInstance().newDocumentBuilder(); - return documentBuilder.parse(in); - } catch (ParserConfigurationException | SAXException | IOException e) { - throw new RuntimeException("Cannot parse", e); - } - }); - - // TODO optimise - try (PipedOutputStream out = new PipedOutputStream(in)) { - node.getSession().exportDocumentView(node.getPath(), out, true, false); - } catch (IOException | RepositoryException e) { - throw new RuntimeException("Cannot export " + node + " in workspace " + Jcr.getWorkspaceName(node), e); - } - Document document = toDo.get(); - cleanJcrDom(document); - return new DOMSource(document); - } catch (IOException | InterruptedException | ExecutionException e1) { - throw new RuntimeException("Cannot parse", e1); - } - - } - - public static void setAttributes(Node source, Content target, NamespaceContext jcrNamespaceContext) - throws RepositoryException { - properties: for (PropertyIterator pit = source.getProperties(); pit.hasNext();) { - Property p = pit.nextProperty(); - // TODO migrate JCR title, last modified, etc. ? - if (p.getName().startsWith("jcr:")) - continue properties; - if (p.isMultiple()) { - List attr = new ArrayList<>(); - for (Value value : p.getValues()) { - attr.add(value.getString()); - } - target.put(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, p.getName()), attr); - } else { - target.put(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, p.getName()), p.getString()); - } - } - } - - public static List typesAsContentClasses(Node source, NamespaceContext jcrNamespaceContext) - throws RepositoryException { - // TODO super types? - List contentClasses = new ArrayList<>(); - contentClasses - .add(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, source.getPrimaryNodeType().getName())); - for (NodeType nodeType : source.getMixinNodeTypes()) { - contentClasses.add(NamespaceUtils.parsePrefixedName(jcrNamespaceContext, nodeType.getName())); - } - // filter out JCR types - for (Iterator it = contentClasses.iterator(); it.hasNext();) { - QName type = it.next(); - if (type.getNamespaceURI().equals(JCR_NT_NAMESPACE_URI) - || type.getNamespaceURI().equals(JCR_MIX_NAMESPACE_URI)) { - it.remove(); - } - } - // target.addContentClasses(contentClasses.toArray(new - // QName[contentClasses.size()])); - return contentClasses; - } - - static final String JCR_NAMESPACE_URI = "http://www.jcp.org/jcr/1.0"; - static final String JCR_NT_NAMESPACE_URI = "http://www.jcp.org/jcr/nt/1.0"; - static final String JCR_MIX_NAMESPACE_URI = "http://www.jcp.org/jcr/mix/1.0"; - - public static void cleanJcrDom(Document document) { - Element documentElement = document.getDocumentElement(); - Set namespaceUris = new HashSet<>(); - cleanJcrDom(documentElement, namespaceUris); - - // remove unused namespaces - NamedNodeMap attrs = documentElement.getAttributes(); - Set toRemove = new HashSet<>(); - for (int i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); -// log.debug("Check "+i+" " + attr); - String prefix = attr.getPrefix(); - if (prefix != null && prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { - String namespaceUri = attr.getValue(); - if (!namespaceUris.contains(namespaceUri)) { - toRemove.add(attr); - // log.debug("Removing "+i+" " + namespaceUri); - } - } - } - for (Attr attr : toRemove) - documentElement.removeAttributeNode(attr); - - } - - private static void cleanJcrDom(Element element, Set namespaceUris) { - NodeList children = element.getElementsByTagName("*"); - for (int i = 0; i < children.getLength(); i++) { - Element child = (Element) children.item(i); - if (!namespaceUris.contains(child.getNamespaceURI())) - namespaceUris.add(child.getNamespaceURI()); - cleanJcrDom(child, namespaceUris); - } - - NamedNodeMap attrs = element.getAttributes(); - attributes: for (int i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); - String namespaceUri = attr.getNamespaceURI(); - if (namespaceUri == null) - continue attributes; - if (JCR_NAMESPACE_URI.equals(namespaceUri)) { - // FIXME probably wrong to change attributes length - element.removeAttributeNode(attr); - continue attributes; - } - if (!namespaceUris.contains(namespaceUri)) - namespaceUris.add(attr.getNamespaceURI()); - - } - - } - - /** singleton */ - private JcrContentUtils() { - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java deleted file mode 100644 index ae8ae80f2..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.argeo.cms.jcr.acr; - -import java.security.PrivilegedAction; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; - -import org.apache.jackrabbit.core.SessionImpl; -import org.argeo.api.acr.spi.ProvidedSession; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** Manages JCR {@link Session} in an ACR context. */ -class JcrSessionAdapter { - private Repository repository; - private Subject subject; - - private ProvidedSession contentSession; - - private Map> threadSessions = Collections.synchronizedMap(new HashMap<>()); - - private boolean closed = false; - - private Thread lastRetrievingThread = null; - - public JcrSessionAdapter(Repository repository, ProvidedSession contentSession, Subject subject) { - this.repository = repository; - this.contentSession = contentSession; - this.subject = subject; - } - - public synchronized void close() { - for (Map sessions : threadSessions.values()) { - for (Session session : sessions.values()) { - JcrUtils.logoutQuietly(session); - } - sessions.clear(); - } - threadSessions.clear(); - closed = true; - } - - public synchronized Session getSession(String workspace) { - if (closed) - throw new IllegalStateException("JCR session adapter is closed."); - - Thread currentThread = Thread.currentThread(); - if (lastRetrievingThread == null) - lastRetrievingThread = currentThread; - - Map threadSession = threadSessions.get(currentThread); - if (threadSession == null) { - threadSession = new HashMap<>(); - threadSessions.put(currentThread, threadSession); - } - - Session session = threadSession.get(workspace); - if (session == null) { - session = Subject.doAs(subject, (PrivilegedAction) () -> { - try { -// String username = CurrentUser.getUsername(subject); -// SimpleCredentials credentials = new SimpleCredentials(username, new char[0]); -// credentials.setAttribute(ProvidedSession.class.getName(), contentSession); - Session sess = repository.login(workspace); - // Jackrabbit specific: - ((SessionImpl)sess).setAttribute(ProvidedSession.class.getName(), contentSession); - return sess; - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot log in to " + workspace, e); - } - }); - threadSession.put(workspace, session); - } - - if (lastRetrievingThread != currentThread) { - try { - session.refresh(true); - } catch (RepositoryException e) { - throw new JcrException("Cannot refresh JCR session " + session, e); - } - } - lastRetrievingThread = currentThread; - return session; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionNamespaceContext.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionNamespaceContext.java deleted file mode 100644 index a55f4a359..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionNamespaceContext.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.argeo.cms.jcr.acr; - -import java.util.Arrays; -import java.util.Iterator; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.xml.namespace.NamespaceContext; - -import org.argeo.jcr.JcrException; - -/** A {@link NamespaceContext} based on a JCR {@link Session}. */ -public class JcrSessionNamespaceContext implements NamespaceContext { - private final Session session; - - public JcrSessionNamespaceContext(Session session) { - this.session = session; - } - - @Override - public String getNamespaceURI(String prefix) { - try { - return session.getNamespaceURI(prefix); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - @Override - public String getPrefix(String namespaceURI) { - try { - return session.getNamespacePrefix(namespaceURI); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - @Override - public Iterator getPrefixes(String namespaceURI) { - try { - return Arrays.asList(session.getNamespacePrefix(namespaceURI)).iterator(); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/argeo.cnd b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/argeo.cnd deleted file mode 100644 index c9e6ee7e2..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/argeo.cnd +++ /dev/null @@ -1,34 +0,0 @@ - - -// GENERIC TYPES -[argeo:remoteRepository] > nt:unstructured -- argeo:uri (STRING) -- argeo:userID (STRING) -+ argeo:password (argeo:encrypted) - -// TABULAR CONTENT -[argeo:table] > nt:file -+ * (argeo:column) * - -[argeo:column] > mix:title -- jcr:requiredType (STRING) = 'STRING' - -[argeo:csv] > nt:resource - -// CRYPTO -[argeo:encrypted] -mixin -// initialization vector used by some algorithms -- argeo:iv (BINARY) - -[argeo:pbeKeySpec] -mixin -- argeo:secretKeyFactory (STRING) -- argeo:salt (BINARY) -- argeo:iterationCount (LONG) -- argeo:keyLength (LONG) -- argeo:secretKeyEncryption (STRING) - -[argeo:pbeSpec] > argeo:pbeKeySpec -mixin -- argeo:cipher (STRING) diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/dn.cnd b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/dn.cnd deleted file mode 100644 index 80849be95..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/dn.cnd +++ /dev/null @@ -1,10 +0,0 @@ -// DN (see https://tools.ietf.org/html/rfc4514) - - - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java deleted file mode 100644 index 35800f895..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java +++ /dev/null @@ -1,475 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import static org.argeo.cms.osgi.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE; -import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX; - -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.servlet.Servlet; - -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.apache.jackrabbit.core.RepositoryContext; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.ArgeoNames; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.jcr.internal.servlet.CmsRemotingServlet; -import org.argeo.cms.jcr.internal.servlet.CmsWebDavServlet; -import org.argeo.cms.jcr.internal.servlet.JcrHttpUtils; -import org.argeo.cms.osgi.DataModelNamespace; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.wiring.BundleCapability; -import org.osgi.framework.wiring.BundleWire; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; -import org.osgi.util.tracker.ServiceTracker; - -/** Implementation of a CMS deployment. */ -public class CmsJcrDeployment { - private final CmsLog log = CmsLog.getLog(getClass()); - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - private DataModels dataModels; - private String webDavConfig = JcrHttpUtils.WEBDAV_CONFIG; - - private boolean argeoDataModelExtensionsAvailable = false; - - // Readiness - private boolean nodeAvailable = false; - -// CmsDeployment cmsDeployment; - public void start() { - dataModels = new DataModels(bc); - - ServiceTracker repoContextSt = new RepositoryContextStc(); - repoContextSt.open(); - // KernelUtils.asyncOpen(repoContextSt); - -// nodeDeployment = CmsJcrActivator.getService(NodeDeployment.class); - - //JcrInitUtils.addToDeployment(cmsDeployment); - -// contentRepository.registerTypes(NamespaceRegistry.PREFIX_JCR, NamespaceRegistry.NAMESPACE_JCR, null); -// contentRepository.registerTypes(NamespaceRegistry.PREFIX_MIX, NamespaceRegistry.NAMESPACE_MIX, null); -// contentRepository.registerTypes(NamespaceRegistry.PREFIX_NT, NamespaceRegistry.NAMESPACE_NT, null); -// // Jackrabbit -// // see -// // https://jackrabbit.apache.org/archive/wiki/JCR/NamespaceRegistry_115513459.html -// contentRepository.registerTypes("rep", "internal", null); - - } - - public void stop() { -// if (nodeHttp != null) -// nodeHttp.destroy(); - - - try { - for (ServiceReference sr : bc - .getServiceReferences(JackrabbitLocalRepository.class, null)) { - bc.getService(sr).destroy(); - } - } catch (InvalidSyntaxException e1) { - log.error("Cannot clean repositories", e1); - } - - } - -// public void setCmsDeployment(CmsDeployment cmsDeployment) { -// this.cmsDeployment = cmsDeployment; -// } - - /** - * Checks whether the deployment is available according to expectations, and - * mark it as available. - */ -// private synchronized void checkReadiness() { -// if (isAvailable()) -// return; -// if (nodeAvailable && userAdminAvailable && (httpExpected ? httpAvailable : true)) { -// String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA); -// String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA); -// availableSince = System.currentTimeMillis(); -// long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); -// String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s"; -// log.info("## ARGEO NODE AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##"); -// if (log.isDebugEnabled()) { -// log.debug("## state: " + state); -// if (data != null) -// log.debug("## data: " + data); -// } -// long begin = bc.getService(bc.getServiceReference(NodeState.class)).getAvailableSince(); -// long initDuration = System.currentTimeMillis() - begin; -// if (log.isTraceEnabled()) -// log.trace("Kernel initialization took " + initDuration + "ms"); -// tributeToFreeSoftware(initDuration); -// } -// } - - private void prepareNodeRepository(Repository deployedNodeRepository, List publishAsLocalRepo) { -// if (availableSince != null) { -// throw new IllegalStateException("Deployment is already available"); -// } - - // home - prepareDataModel(CmsConstants.NODE_REPOSITORY, deployedNodeRepository, publishAsLocalRepo); - - // init from backup -// if (deployConfig.isFirstInit()) { -// Path restorePath = Paths.get(System.getProperty("user.dir"), "restore"); -// if (Files.exists(restorePath)) { -// if (log.isDebugEnabled()) -// log.debug("Found backup " + restorePath + ", restoring it..."); -// LogicalRestore logicalRestore = new LogicalRestore(bc, deployedNodeRepository, restorePath); -// KernelUtils.doAsDataAdmin(logicalRestore); -// log.info("Restored backup from " + restorePath); -// } -// } - - // init from repository -// Collection> initRepositorySr; -// try { -// initRepositorySr = bc.getServiceReferences(Repository.class, -// "(" + CmsConstants.CN + "=" + CmsConstants.NODE_INIT + ")"); -// } catch (InvalidSyntaxException e1) { -// throw new IllegalArgumentException(e1); -// } -// Iterator> it = initRepositorySr.iterator(); -// while (it.hasNext()) { -// ServiceReference sr = it.next(); -// Object labeledUri = sr.getProperties().get(LdapAttrs.labeledURI.name()); -// Repository initRepository = bc.getService(sr); -// if (log.isDebugEnabled()) -// log.debug("Found init repository " + labeledUri + ", copying it..."); -// initFromRepository(deployedNodeRepository, initRepository); -// log.info("Node repository initialised from " + labeledUri); -// } - } - - /** Init from a (typically remote) repository. */ - private void initFromRepository(Repository deployedNodeRepository, Repository initRepository) { - Session initSession = null; - try { - initSession = initRepository.login(); - workspaces: for (String workspaceName : initSession.getWorkspace().getAccessibleWorkspaceNames()) { - if ("security".equals(workspaceName)) - continue workspaces; - if (log.isDebugEnabled()) - log.debug("Copying workspace " + workspaceName + " from init repository..."); - long begin = System.currentTimeMillis(); - Session targetSession = null; - Session sourceSession = null; - try { - try { - targetSession = CmsJcrUtils.openDataAdminSession(deployedNodeRepository, workspaceName); - } catch (IllegalArgumentException e) {// no such workspace - Session adminSession = CmsJcrUtils.openDataAdminSession(deployedNodeRepository, null); - try { - adminSession.getWorkspace().createWorkspace(workspaceName); - } finally { - Jcr.logout(adminSession); - } - targetSession = CmsJcrUtils.openDataAdminSession(deployedNodeRepository, workspaceName); - } - sourceSession = initRepository.login(workspaceName); -// JcrUtils.copyWorkspaceXml(sourceSession, targetSession); - // TODO deal with referenceable nodes - JcrUtils.copy(sourceSession.getRootNode(), targetSession.getRootNode()); - targetSession.save(); - long duration = System.currentTimeMillis() - begin; - if (log.isDebugEnabled()) - log.debug("Copied workspace " + workspaceName + " from init repository in " + (duration / 1000) - + " s"); - } catch (Exception e) { - log.error("Cannot copy workspace " + workspaceName + " from init repository.", e); - } finally { - Jcr.logout(sourceSession); - Jcr.logout(targetSession); - } - } - } catch (RepositoryException e) { - throw new JcrException(e); - } finally { - Jcr.logout(initSession); - } - } - - private void prepareHomeRepository(RepositoryImpl deployedRepository) { - Session adminSession = KernelUtils.openAdminSession(deployedRepository); - try { - argeoDataModelExtensionsAvailable = Arrays - .asList(adminSession.getWorkspace().getNamespaceRegistry().getURIs()) - .contains(ArgeoNames.ARGEO_NAMESPACE); - } catch (RepositoryException e) { - log.warn("Cannot check whether Argeo namespace is registered assuming it isn't.", e); - argeoDataModelExtensionsAvailable = false; - } finally { - JcrUtils.logoutQuietly(adminSession); - } - - // Publish home with the highest service ranking - Hashtable regProps = new Hashtable<>(); - regProps.put(CmsConstants.CN, CmsConstants.EGO_REPOSITORY); - regProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); - Repository egoRepository = new EgoRepository(deployedRepository, false); - bc.registerService(Repository.class, egoRepository, regProps); - registerRepositoryServlets(CmsConstants.EGO_REPOSITORY, egoRepository); - - // Keyring only if Argeo extensions are available -// if (argeoDataModelExtensionsAvailable) { -// new ServiceTracker(bc, CallbackHandler.class, null) { -// -// @Override -// public CallbackHandler addingService(ServiceReference reference) { -// NodeKeyRing nodeKeyring = new NodeKeyRing(egoRepository); -// CallbackHandler callbackHandler = bc.getService(reference); -// nodeKeyring.setDefaultCallbackHandler(callbackHandler); -// bc.registerService(LangUtils.names(Keyring.class, CryptoKeyring.class, ManagedService.class), -// nodeKeyring, LangUtils.dict(Constants.SERVICE_PID, CmsConstants.NODE_KEYRING_PID)); -// return callbackHandler; -// } -// -// }.open(); -// } - } - - /** Session is logged out. */ - private void prepareDataModel(String cn, Repository repository, List publishAsLocalRepo) { - Session adminSession = KernelUtils.openAdminSession(repository); - try { - Set processed = new HashSet(); - bundles: for (Bundle bundle : bc.getBundles()) { - BundleWiring wiring = bundle.adapt(BundleWiring.class); - if (wiring == null) - continue bundles; - if (CmsConstants.NODE_REPOSITORY.equals(cn))// process all data models - processWiring(cn, adminSession, wiring, processed, false, publishAsLocalRepo); - else { - List capabilities = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE); - for (BundleCapability capability : capabilities) { - String dataModelName = (String) capability.getAttributes().get(DataModelNamespace.NAME); - if (dataModelName.equals(cn))// process only own data model - processWiring(cn, adminSession, wiring, processed, false, publishAsLocalRepo); - } - } - } - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - - private void processWiring(String cn, Session adminSession, BundleWiring wiring, Set processed, - boolean importListedAbstractModels, List publishAsLocalRepo) { - // recursively process requirements first - List requiredWires = wiring.getRequiredWires(CMS_DATA_MODEL_NAMESPACE); - for (BundleWire wire : requiredWires) { - processWiring(cn, adminSession, wire.getProviderWiring(), processed, true, publishAsLocalRepo); - } - - List capabilities = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE); - capabilities: for (BundleCapability capability : capabilities) { - if (!importListedAbstractModels - && KernelUtils.asBoolean((String) capability.getAttributes().get(DataModelNamespace.ABSTRACT))) { - continue capabilities; - } - boolean publish = registerDataModelCapability(cn, adminSession, capability, processed); - if (publish) - publishAsLocalRepo.add((String) capability.getAttributes().get(DataModelNamespace.NAME)); - } - } - - private boolean registerDataModelCapability(String cn, Session adminSession, BundleCapability capability, - Set processed) { - Map attrs = capability.getAttributes(); - String name = (String) attrs.get(DataModelNamespace.NAME); - if (processed.contains(name)) { - if (log.isTraceEnabled()) - log.trace("Data model " + name + " has already been processed"); - return false; - } - - // CND - String path = (String) attrs.get(DataModelNamespace.CND); - if (path != null) { - File dataModel = bc.getBundle().getDataFile("dataModels/" + path); - if (!dataModel.exists()) { - URL url = capability.getRevision().getBundle().getResource(path); - if (url == null) - throw new IllegalArgumentException("No data model '" + name + "' found under path " + path); - try (Reader reader = new InputStreamReader(url.openStream())) { - CndImporter.registerNodeTypes(reader, adminSession, true); - processed.add(name); - dataModel.getParentFile().mkdirs(); - dataModel.createNewFile(); - if (log.isDebugEnabled()) - log.debug("Registered CND " + url); - } catch (Exception e) { - log.error("Cannot import CND " + url, e); - } - } - } - - if (KernelUtils.asBoolean((String) attrs.get(DataModelNamespace.ABSTRACT))) - return false; - // Non abstract - boolean isStandalone = isStandalone(name); - boolean publishLocalRepo; - if (isStandalone && name.equals(cn))// includes the node itself - publishLocalRepo = true; - else if (!isStandalone && cn.equals(CmsConstants.NODE_REPOSITORY)) - publishLocalRepo = true; - else - publishLocalRepo = false; - - return publishLocalRepo; - } - - boolean isStandalone(String dataModelName) { - return true; - //return cmsDeployment.getProps(CmsConstants.NODE_REPOS_FACTORY_PID, dataModelName) != null; - } - - private void publishLocalRepo(String dataModelName, Repository repository) { - Hashtable properties = new Hashtable<>(); - properties.put(CmsConstants.CN, dataModelName); - LocalRepository localRepository; - String[] classes; - if (repository instanceof RepositoryImpl) { - localRepository = new JackrabbitLocalRepository((RepositoryImpl) repository, dataModelName); - classes = new String[] { Repository.class.getName(), LocalRepository.class.getName(), - JackrabbitLocalRepository.class.getName() }; - } else { - localRepository = new LocalRepository(repository, dataModelName); - classes = new String[] { Repository.class.getName(), LocalRepository.class.getName() }; - } - bc.registerService(classes, localRepository, properties); - - // TODO make it configurable - registerRepositoryServlets(dataModelName, localRepository); - if (log.isTraceEnabled()) - log.trace("Published data model " + dataModelName); - } - -// @Override -// public synchronized Long getAvailableSince() { -// return availableSince; -// } -// -// public synchronized boolean isAvailable() { -// return availableSince != null; -// } - - protected void registerRepositoryServlets(String alias, Repository repository) { - registerRemotingServlet(alias, repository); - registerWebdavServlet(alias, repository); - } - - protected void registerWebdavServlet(String alias, Repository repository) { - CmsWebDavServlet webdavServlet = new CmsWebDavServlet(alias, repository); - Hashtable ip = new Hashtable<>(); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsWebDavServlet.INIT_PARAM_RESOURCE_CONFIG, webDavConfig); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsWebDavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, - "/" + alias); - - ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/" + alias + "/*"); - ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, - "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=" + CmsConstants.PATH_DATA + ")"); - bc.registerService(Servlet.class, webdavServlet, ip); - } - - protected void registerRemotingServlet(String alias, Repository repository) { - CmsRemotingServlet remotingServlet = new CmsRemotingServlet(alias, repository); - Hashtable ip = new Hashtable<>(); - ip.put(CmsConstants.CN, alias); - // Properties ip = new Properties(); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, - "/" + alias); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, - "Negotiate"); - - // Looks like a bug in Jackrabbit remoting init - Path tmpDir; - try { - tmpDir = Files.createTempDirectory("remoting_" + alias); - } catch (IOException e) { - throw new RuntimeException("Cannot create temp directory for remoting servlet", e); - } - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_HOME, tmpDir.toString()); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_TMP_DIRECTORY, - "remoting_" + alias); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG, - JcrHttpUtils.DEFAULT_PROTECTED_HANDLERS); - ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_CREATE_ABSOLUTE_URI, "false"); - - ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/" + alias + "/*"); - ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, - "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=" + CmsConstants.PATH_JCR + ")"); - bc.registerService(Servlet.class, remotingServlet, ip); - } - - private class RepositoryContextStc extends ServiceTracker { - - public RepositoryContextStc() { - super(bc, RepositoryContext.class, null); - } - - @Override - public RepositoryContext addingService(ServiceReference reference) { - RepositoryContext repoContext = bc.getService(reference); - String cn = (String) reference.getProperty(CmsConstants.CN); - if (cn != null) { - List publishAsLocalRepo = new ArrayList<>(); - if (cn.equals(CmsConstants.NODE_REPOSITORY)) { -// JackrabbitDataModelMigration.clearRepositoryCaches(repoContext.getRepositoryConfig()); - prepareNodeRepository(repoContext.getRepository(), publishAsLocalRepo); - // TODO separate home repository - prepareHomeRepository(repoContext.getRepository()); - registerRepositoryServlets(cn, repoContext.getRepository()); - nodeAvailable = true; -// checkReadiness(); - } else { - prepareDataModel(cn, repoContext.getRepository(), publishAsLocalRepo); - } - // Publish all at once, so that bundles with multiple CNDs are consistent - for (String dataModelName : publishAsLocalRepo) - publishLocalRepo(dataModelName, repoContext.getRepository()); - } - return repoContext; - } - - @Override - public void modifiedService(ServiceReference reference, RepositoryContext service) { - } - - @Override - public void removedService(ServiceReference reference, RepositoryContext service) { - } - - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrFsProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrFsProvider.java deleted file mode 100644 index 0099b3bed..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrFsProvider.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.Path; -import java.nio.file.spi.FileSystemProvider; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jackrabbit.fs.AbstractJackrabbitFsProvider; -import org.argeo.jcr.fs.JcrFileSystem; -import org.argeo.jcr.fs.JcrFileSystemProvider; -import org.argeo.jcr.fs.JcrFsException; - -/** Implementation of an {@link FileSystemProvider} based on Jackrabbit. */ -public class CmsJcrFsProvider extends AbstractJackrabbitFsProvider { - private Map fileSystems = new HashMap<>(); - - private RepositoryFactory repositoryFactory; - private Repository repository; - - @Override - public String getScheme() { - return CmsConstants.SCHEME_NODE; - } - - @Override - public FileSystem newFileSystem(URI uri, Map env) throws IOException { -// BundleContext bc = FrameworkUtil.getBundle(CmsJcrFsProvider.class).getBundleContext(); - String username = CurrentUser.getUsername(); - if (username == null) { - // TODO deal with anonymous - return null; - } - if (fileSystems.containsKey(username)) - throw new FileSystemAlreadyExistsException("CMS file system already exists for user " + username); - - try { - String host = uri.getHost(); - if (host != null && !host.trim().equals("")) { - URI repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), "/jcr/node", null, null); -// RepositoryFactory repositoryFactory = bc.getService(bc.getServiceReference(RepositoryFactory.class)); - Repository repository = CmsJcrUtils.getRepositoryByUri(repositoryFactory, repoUri.toString()); - CmsFileSystem fileSystem = new CmsFileSystem(this, repository); - fileSystems.put(username, fileSystem); - return fileSystem; - } else { -// Repository repository = bc.getService( -// bc.getServiceReferences(Repository.class, "(cn=" + CmsConstants.EGO_REPOSITORY + ")") -// .iterator().next()); - - // Session session = repository.login(); - CmsFileSystem fileSystem = new CmsFileSystem(this, repository); - fileSystems.put(username, fileSystem); - return fileSystem; - } - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Cannot open file system " + uri + " for user " + username, e); - } - } - - @Override - public FileSystem getFileSystem(URI uri) { - return currentUserFileSystem(); - } - - @Override - public Path getPath(URI uri) { - JcrFileSystem fileSystem = currentUserFileSystem(); - String path = uri.getPath(); - if (fileSystem == null) - try { - fileSystem = (JcrFileSystem) newFileSystem(uri, new HashMap()); - } catch (IOException e) { - throw new JcrFsException("Could not autocreate file system", e); - } - return fileSystem.getPath(path); - } - - protected JcrFileSystem currentUserFileSystem() { - String username = CurrentUser.getUsername(); - return fileSystems.get(username); - } - - public Node getUserHome(Repository repository) { - try { - Session session = repository.login(CmsConstants.HOME_WORKSPACE); - return CmsJcrUtils.getUserHome(session); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get user home", e); - } - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - static class CmsFileSystem extends JcrFileSystem { - public CmsFileSystem(JcrFileSystemProvider provider, Repository repository) throws IOException { - super(provider, repository); - } - - public boolean skipNode(Node node) throws RepositoryException { -// if (node.isNodeType(NodeType.NT_HIERARCHY_NODE) || node.isNodeType(NodeTypes.NODE_USER_HOME) -// || node.isNodeType(NodeTypes.NODE_GROUP_HOME)) - if (node.isNodeType(NodeType.NT_HIERARCHY_NODE)) - return false; - // FIXME Better identifies home - if (node.hasProperty(Property.JCR_ID)) - return false; - return true; - } - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java deleted file mode 100644 index 090ec67ef..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.nio.file.Path; - -/** Centralises access to the default node deployment directories. */ -@Deprecated -public class CmsPaths { - public static Path getRepoDirPath(String cn) { - return KernelUtils.getOsgiInstancePath(KernelConstants.DIR_REPOS + '/' + cn); - } - - public static Path getRepoIndexesBase() { - return KernelUtils.getOsgiInstancePath(KernelConstants.DIR_INDEXES); - } - - /** Singleton. */ - private CmsPaths() { - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsWorkspaceIndexer.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsWorkspaceIndexer.java deleted file mode 100644 index 69b98dc3a..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsWorkspaceIndexer.java +++ /dev/null @@ -1,342 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.util.GregorianCalendar; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.version.VersionManager; - -import org.apache.jackrabbit.api.JackrabbitValue; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.JcrUtils; - -/** Ensure consistency of files, folder and last modified nodes. */ -class CmsWorkspaceIndexer implements EventListener { - private final static CmsLog log = CmsLog.getLog(CmsWorkspaceIndexer.class); - -// private final static String MIX_ETAG = "mix:etag"; - private final static String JCR_ETAG = "jcr:etag"; -// private final static String JCR_LAST_MODIFIED = "jcr:lastModified"; -// private final static String JCR_LAST_MODIFIED_BY = "jcr:lastModifiedBy"; -// private final static String JCR_MIXIN_TYPES = "jcr:mixinTypes"; - private final static String JCR_DATA = "jcr:data"; - private final static String JCR_CONTENT = "jcr:data"; - - private String cn; - private String workspaceName; - private RepositoryImpl repositoryImpl; - private Session session; - private VersionManager versionManager; - - private LinkedBlockingDeque toProcess = new LinkedBlockingDeque<>(); - private IndexingThread indexingThread; - private AtomicBoolean stopping = new AtomicBoolean(false); - - public CmsWorkspaceIndexer(RepositoryImpl repositoryImpl, String cn, String workspaceName) - throws RepositoryException { - this.cn = cn; - this.workspaceName = workspaceName; - this.repositoryImpl = repositoryImpl; - } - - public void init() { - session = KernelUtils.openAdminSession(repositoryImpl, workspaceName); - try { - String[] nodeTypes = { NodeType.NT_FILE, NodeType.MIX_LAST_MODIFIED }; - session.getWorkspace().getObservationManager().addEventListener(this, - Event.NODE_ADDED | Event.PROPERTY_CHANGED, "/", true, null, nodeTypes, true); - versionManager = session.getWorkspace().getVersionManager(); - - indexingThread = new IndexingThread(); - indexingThread.start(); - } catch (RepositoryException e1) { - throw new IllegalStateException(e1); - } - } - - public void destroy() { - stopping.set(true); - indexingThread.interrupt(); - // TODO make it configurable - try { - indexingThread.join(10 * 60 * 1000); - } catch (InterruptedException e1) { - log.warn("Indexing thread interrupted. Will log out session."); - } - - try { - session.getWorkspace().getObservationManager().removeEventListener(this); - } catch (RepositoryException e) { - if (log.isTraceEnabled()) - log.warn("Cannot unregistered JCR event listener", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - private synchronized void processEvents(EventIterator events) { - long begin = System.currentTimeMillis(); - long count = 0; - while (events.hasNext()) { - Event event = events.nextEvent(); - try { - toProcess.put(event); - } catch (InterruptedException e) { - e.printStackTrace(); - } -// processEvent(event); - count++; - } - long duration = System.currentTimeMillis() - begin; - if (log.isTraceEnabled()) - log.trace("Processed " + count + " events in " + duration + " ms"); - notifyAll(); - } - - protected synchronized void processEvent(Event event) { - try { - String eventPath = event.getPath(); - if (event.getType() == Event.NODE_ADDED) { - if (!versionManager.isCheckedOut(eventPath)) - return;// ignore checked-in nodes - if (log.isTraceEnabled()) - log.trace("NODE_ADDED " + eventPath); -// session.refresh(true); - session.refresh(false); - Node node = session.getNode(eventPath); - Node parentNode = node.getParent(); - if (parentNode.isNodeType(NodeType.NT_FILE)) { - if (node.isNodeType(NodeType.NT_UNSTRUCTURED)) { - if (!node.isNodeType(NodeType.MIX_LAST_MODIFIED)) - node.addMixin(NodeType.MIX_LAST_MODIFIED); - Property property = node.getProperty(Property.JCR_DATA); - String etag = toEtag(property.getValue()); - session.save(); - node.setProperty(JCR_ETAG, etag); - if (log.isTraceEnabled()) - log.trace("ETag and last modified added to new " + node); - } else if (node.isNodeType(NodeType.NT_RESOURCE)) { -// if (!node.isNodeType(MIX_ETAG)) -// node.addMixin(MIX_ETAG); -// session.save(); -// Property property = node.getProperty(Property.JCR_DATA); -// String etag = toEtag(property.getValue()); -// node.setProperty(JCR_ETAG, etag); -// session.save(); - } -// setLastModifiedRecursive(parentNode, event); -// session.save(); -// if (log.isTraceEnabled()) -// log.trace("ETag and last modified added to new " + node); - } - -// if (node.isNodeType(NodeType.NT_FOLDER)) { -// setLastModifiedRecursive(node, event); -// session.save(); -// if (log.isTraceEnabled()) -// log.trace("Last modified added to new " + node); -// } - } else if (event.getType() == Event.PROPERTY_CHANGED) { - String propertyName = extractItemName(eventPath); - // skip if last modified properties are explicitly set - if (!propertyName.equals(JCR_DATA)) - return; -// if (propertyName.equals(JCR_LAST_MODIFIED)) -// return; -// if (propertyName.equals(JCR_LAST_MODIFIED_BY)) -// return; -// if (propertyName.equals(JCR_MIXIN_TYPES)) -// return; -// if (propertyName.equals(JCR_ETAG)) -// return; - - if (log.isTraceEnabled()) - log.trace("PROPERTY_CHANGED " + eventPath); - - if (!session.propertyExists(eventPath)) - return; - session.refresh(false); - Property property = session.getProperty(eventPath); - Node node = property.getParent(); - if (property.getType() == PropertyType.BINARY && propertyName.equals(JCR_DATA) - && node.isNodeType(NodeType.NT_UNSTRUCTURED)) { - String etag = toEtag(property.getValue()); - node.setProperty(JCR_ETAG, etag); - Node parentNode = node.getParent(); - if (parentNode.isNodeType(NodeType.MIX_LAST_MODIFIED)) { - setLastModified(parentNode, event); - } - if (log.isTraceEnabled()) - log.trace("ETag and last modified updated for " + node); - } -// setLastModified(node, event); -// session.save(); -// if (log.isTraceEnabled()) -// log.trace("ETag and last modified updated for " + node); - } else if (event.getType() == Event.NODE_REMOVED) { - String removeNodePath = eventPath; - String nodeName = extractItemName(eventPath); - if (JCR_CONTENT.equals(nodeName)) // parent is a file, deleted anyhow - return; - if (log.isTraceEnabled()) - log.trace("NODE_REMOVED " + eventPath); -// String parentPath = JcrUtils.parentPath(removeNodePath); -// session.refresh(true); -// setLastModified(parentPath, event); -// session.save(); - if (log.isTraceEnabled()) - log.trace("Last modified updated for parents of removed " + removeNodePath); - } - } catch (Exception e) { - if (log.isTraceEnabled()) - log.warn("Cannot process event " + event, e); - } finally { -// try { -// session.refresh(true); -// if (session.hasPendingChanges()) -// session.save(); -//// session.refresh(false); -// } catch (RepositoryException e) { -// if (log.isTraceEnabled()) -// log.warn("Cannot refresh JCR session", e); -// } - } - - } - - private String extractItemName(String path) { - if (path == null || path.length() <= 1) - return null; - int lastIndex = path.lastIndexOf('/'); - if (lastIndex >= 0) { - return path.substring(lastIndex + 1); - } else { - return path; - } - } - - @Override - public void onEvent(EventIterator events) { - processEvents(events); -// Runnable toRun = new Runnable() { -// -// @Override -// public void run() { -// processEvents(events); -// } -// }; -// Future future = Activator.getInternalExecutorService().submit(toRun); -// try { -// // make the call synchronous -// future.get(60, TimeUnit.SECONDS); -// } catch (TimeoutException | ExecutionException | InterruptedException e) { -// // silent -// } - } - - static String toEtag(Value v) { - if (v instanceof JackrabbitValue) { - JackrabbitValue value = (JackrabbitValue) v; - return '\"' + value.getContentIdentity() + '\"'; - } else { - return null; - } - - } - - protected synchronized void setLastModified(Node node, Event event) throws RepositoryException { - GregorianCalendar calendar = new GregorianCalendar(); - calendar.setTimeInMillis(event.getDate()); - node.setProperty(Property.JCR_LAST_MODIFIED, calendar); - node.setProperty(Property.JCR_LAST_MODIFIED_BY, event.getUserID()); - if (log.isTraceEnabled()) - log.trace("Last modified set on " + node); - } - - /** Recursively set the last updated time on parents. */ - protected synchronized void setLastModifiedRecursive(Node node, Event event) throws RepositoryException { - if (versionManager.isCheckedOut(node.getPath())) { - if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) { - setLastModified(node, event); - } - if (node.isNodeType(NodeType.NT_FOLDER) && !node.isNodeType(NodeType.MIX_LAST_MODIFIED)) { - node.addMixin(NodeType.MIX_LAST_MODIFIED); - if (log.isTraceEnabled()) - log.trace("Last modified mix-in added to " + node); - } - - } - - // end condition - if (node.getDepth() == 0) { -// try { -// node.getSession().save(); -// } catch (RepositoryException e) { -// log.warn("Cannot index workspace", e); -// } - return; - } else { - Node parent = node.getParent(); - setLastModifiedRecursive(parent, event); - } - } - - /** - * Recursively set the last updated time on parents. Useful to use paths when - * dealing with deletions. - */ - protected synchronized void setLastModifiedRecursive(String path, Event event) throws RepositoryException { - // root node will always exist, so end condition is delegated to the other - // recursive setLastModified method - if (session.nodeExists(path)) { - setLastModifiedRecursive(session.getNode(path), event); - } else { - setLastModifiedRecursive(JcrUtils.parentPath(path), event); - } - } - - @Override - public String toString() { - return "Indexer for workspace " + workspaceName + " of repository " + cn; - } - - class IndexingThread extends Thread { - - public IndexingThread() { - super(CmsWorkspaceIndexer.this.toString()); - // TODO Auto-generated constructor stub - } - - @Override - public void run() { - life: while (session != null && session.isLive()) { - try { - Event nextEvent = toProcess.take(); - processEvent(nextEvent); - } catch (InterruptedException e) { - // silent - interrupted(); - } - - if (stopping.get() && toProcess.isEmpty()) { - break life; - } - } - if (log.isDebugEnabled()) - log.debug(CmsWorkspaceIndexer.this.toString() + " has shut down."); - } - - } - -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/DataModels.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/DataModels.java deleted file mode 100644 index f2196bd41..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/DataModels.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import static org.argeo.cms.osgi.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.osgi.DataModelNamespace; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleEvent; -import org.osgi.framework.BundleListener; -import org.osgi.framework.wiring.BundleCapability; -import org.osgi.framework.wiring.BundleWire; -import org.osgi.framework.wiring.BundleWiring; - -class DataModels implements BundleListener { - private final static CmsLog log = CmsLog.getLog(DataModels.class); - - private Map dataModels = new TreeMap<>(); - - public DataModels(BundleContext bc) { - for (Bundle bundle : bc.getBundles()) - processBundle(bundle, null); - bc.addBundleListener(this); - } - - public List getNonAbstractDataModels() { - List res = new ArrayList<>(); - for (String name : dataModels.keySet()) { - DataModel dataModel = dataModels.get(name); - if (!dataModel.isAbstract()) - res.add(dataModel); - } - // TODO reorder? - return res; - } - - @Override - public void bundleChanged(BundleEvent event) { - if (event.getType() == Bundle.RESOLVED) { - processBundle(event.getBundle(), null); - } else if (event.getType() == Bundle.UNINSTALLED) { - BundleWiring wiring = event.getBundle().adapt(BundleWiring.class); - List providedDataModels = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE); - if (providedDataModels.size() == 0) - return; - for (BundleCapability bundleCapability : providedDataModels) { - dataModels.remove(bundleCapability.getAttributes().get(DataModelNamespace.NAME)); - } - } - - } - - protected void processBundle(Bundle bundle, List scannedBundles) { - if (scannedBundles != null && scannedBundles.contains(bundle)) - throw new IllegalStateException("Cycle in CMS data model requirements for " + bundle); - BundleWiring wiring = bundle.adapt(BundleWiring.class); - if (wiring == null) { - int bundleState = bundle.getState(); - if (bundleState != Bundle.INSTALLED && bundleState != Bundle.UNINSTALLED) {// ignore unresolved bundles - log.warn("Bundle " + bundle.getSymbolicName() + " #" + bundle.getBundleId() + " (" - + bundle.getLocation() + ") cannot be adapted to a wiring"); - } else { - if (log.isTraceEnabled()) - log.warn("Bundle " + bundle.getSymbolicName() + " is not resolved."); - } - return; - } - List providedDataModels = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE); - if (providedDataModels.size() == 0) - return; - List requiredDataModels = wiring.getRequiredWires(CMS_DATA_MODEL_NAMESPACE); - // process requirements first - for (BundleWire bundleWire : requiredDataModels) { - List nextScannedBundles = new ArrayList<>(); - if (scannedBundles != null) - nextScannedBundles.addAll(scannedBundles); - nextScannedBundles.add(bundle); - Bundle providerBundle = bundleWire.getProvider().getBundle(); - processBundle(providerBundle, nextScannedBundles); - } - for (BundleCapability bundleCapability : providedDataModels) { - String name = (String) bundleCapability.getAttributes().get(DataModelNamespace.NAME); - assert name != null; - if (!dataModels.containsKey(name)) { - DataModel dataModel = new DataModel(name, bundleCapability, requiredDataModels); - dataModels.put(dataModel.getName(), dataModel); - } - } - } - - /** Return a negative depth if dataModel is required by ref, 0 otherwise. */ - static int required(DataModel ref, DataModel dataModel, int depth) { - for (DataModel dm : ref.getRequired()) { - if (dm.equals(dataModel))// found here - return depth - 1; - int d = required(dm, dataModel, depth - 1); - if (d != 0)// found deeper - return d; - } - return 0;// not found - } - - class DataModel { - private final String name; - private final boolean abstrct; - // private final boolean standalone; - private final String cnd; - private final List required; - - private DataModel(String name, BundleCapability bundleCapability, List requiredDataModels) { - assert CMS_DATA_MODEL_NAMESPACE.equals(bundleCapability.getNamespace()); - this.name = name; - Map attrs = bundleCapability.getAttributes(); - abstrct = KernelUtils.asBoolean((String) attrs.get(DataModelNamespace.ABSTRACT)); - // standalone = KernelUtils.asBoolean((String) - // attrs.get(DataModelNamespace.CAPABILITY_STANDALONE_ATTRIBUTE)); - cnd = (String) attrs.get(DataModelNamespace.CND); - List req = new ArrayList<>(); - for (BundleWire wire : requiredDataModels) { - String requiredDataModelName = (String) wire.getCapability().getAttributes() - .get(DataModelNamespace.NAME); - assert requiredDataModelName != null; - DataModel requiredDataModel = dataModels.get(requiredDataModelName); - if (requiredDataModel == null) - throw new IllegalStateException("No required data model " + requiredDataModelName); - req.add(requiredDataModel); - } - required = Collections.unmodifiableList(req); - } - - public String getName() { - return name; - } - - public boolean isAbstract() { - return abstrct; - } - - // public boolean isStandalone() { - // return !isAbstract(); - // } - - public String getCnd() { - return cnd; - } - - public List getRequired() { - return required; - } - - // @Override - // public int compareTo(DataModel o) { - // if (equals(o)) - // return 0; - // int res = required(this, o, 0); - // if (res != 0) - // return res; - // // the other way round - // res = required(o, this, 0); - // if (res != 0) - // return -res; - // return 0; - // } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof DataModel) - return ((DataModel) obj).name.equals(name); - return false; - } - - @Override - public String toString() { - return "Data model " + name; - } - - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java deleted file mode 100644 index ef785f93d..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java +++ /dev/null @@ -1,264 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.security.PrivilegedAction; -import java.text.SimpleDateFormat; -import java.util.HashSet; -import java.util.Set; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.security.Privilege; -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; - -import org.argeo.api.cms.CmsAuth; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrRepositoryWrapper; -import org.argeo.jcr.JcrUtils; - -/** - * Make sure each user has a home directory available. - */ -class EgoRepository extends JcrRepositoryWrapper { - - /** The home base path. */ -// private String homeBasePath = KernelConstants.DEFAULT_HOME_BASE_PATH; -// private String usersBasePath = KernelConstants.DEFAULT_USERS_BASE_PATH; -// private String groupsBasePath = KernelConstants.DEFAULT_GROUPS_BASE_PATH; - - private Set checkedUsers = new HashSet(); - - private SimpleDateFormat usersDatePath = new SimpleDateFormat("YYYY/MM"); - - private String defaultHomeWorkspace = CmsConstants.HOME_WORKSPACE; - private String defaultGroupsWorkspace = CmsConstants.SRV_WORKSPACE; -// private String defaultGuestsWorkspace = NodeConstants.GUESTS_WORKSPACE; - private final boolean remote; - - public EgoRepository(Repository repository, boolean remote) { - super(repository); - this.remote = remote; - putDescriptor(CmsConstants.CN, CmsConstants.EGO_REPOSITORY); - if (!remote) { - LoginContext lc; - try { - lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_DATA_ADMIN); - lc.login(); - } catch (javax.security.auth.login.LoginException e1) { - throw new IllegalStateException("Cannot login as system", e1); - } - Subject.doAs(lc.getSubject(), new PrivilegedAction() { - - @Override - public Void run() { - loginOrCreateWorkspace(defaultHomeWorkspace); - loginOrCreateWorkspace(defaultGroupsWorkspace); - return null; - } - - }); - } - } - - private void loginOrCreateWorkspace(String workspace) { - Session adminSession = null; - try { - adminSession = JcrUtils.loginOrCreateWorkspace(getRepository(workspace), workspace); -// JcrUtils.addPrivilege(adminSession, "/", NodeConstants.ROLE_USER, Privilege.JCR_READ); - -// initJcr(adminSession); - } catch (RepositoryException e) { - throw new JcrException("Cannot init JCR home", e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - -// @Override -// public Session login(Credentials credentials, String workspaceName) -// throws LoginException, NoSuchWorkspaceException, RepositoryException { -// if (workspaceName == null) { -// return super.login(credentials, getUserHomeWorkspace()); -// } else { -// return super.login(credentials, workspaceName); -// } -// } - - protected String getUserHomeWorkspace() { - // TODO base on JAAS Subject metadata - return defaultHomeWorkspace; - } - - protected String getGroupsWorkspace() { - // TODO base on JAAS Subject metadata - return defaultGroupsWorkspace; - } - -// protected String getGuestsWorkspace() { -// // TODO base on JAAS Subject metadata -// return defaultGuestsWorkspace; -// } - - @Override - protected void processNewSession(Session session, String workspaceName) { - String username = session.getUserID(); - if (username == null || username.toString().equals("")) - return; - if (session.getUserID().equals(CmsConstants.ROLE_ANONYMOUS)) - return; - - String userHomeWorkspace = getUserHomeWorkspace(); - if (workspaceName == null || !workspaceName.equals(userHomeWorkspace)) - return; - - if (checkedUsers.contains(username)) - return; - Session adminSession = KernelUtils.openAdminSession(getRepository(workspaceName), workspaceName); - try { - syncJcr(adminSession, username); - checkedUsers.add(username); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - - /* - * JCR - */ - /** Session is logged out. */ - private void initJcr(Session adminSession) { - try { -// JcrUtils.mkdirs(adminSession, homeBasePath); -// JcrUtils.mkdirs(adminSession, groupsBasePath); - adminSession.save(); - -// JcrUtils.addPrivilege(adminSession, homeBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); -// JcrUtils.addPrivilege(adminSession, groupsBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); - adminSession.save(); - } catch (RepositoryException e) { - throw new JcrException("Cannot initialize home repository", e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - - protected synchronized void syncJcr(Session adminSession, String username) { - // only in the default workspace -// if (workspaceName != null) -// return; - // skip system users - if (username.endsWith(CmsConstants.SYSTEM_ROLES_BASEDN)) - return; - - try { - Node userHome = CmsJcrUtils.getUserHome(adminSession, username); - if (userHome == null) { -// String homePath = generateUserPath(username); - String userId = extractUserId(username); -// if (adminSession.itemExists(homePath))// duplicate user id -// userHome = adminSession.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath)); -// else -// userHome = JcrUtils.mkdirs(adminSession, homePath); - userHome = adminSession.getRootNode().addNode(userId); -// userHome.addMixin(NodeTypes.NODE_USER_HOME); - userHome.addMixin(NodeType.MIX_CREATED); - userHome.addMixin(NodeType.MIX_TITLE); - userHome.setProperty(Property.JCR_ID, username); - // TODO use display name - userHome.setProperty(Property.JCR_TITLE, userId); -// userHome.setProperty(NodeNames.LDAP_UID, username); - adminSession.save(); - - JcrUtils.clearAccessControList(adminSession, userHome.getPath(), username); - JcrUtils.addPrivilege(adminSession, userHome.getPath(), username, Privilege.JCR_ALL); -// JackrabbitSecurityUtils.denyPrivilege(adminSession, userHome.getPath(), NodeConstants.ROLE_USER, -// Privilege.JCR_READ); - } - if (adminSession.hasPendingChanges()) - adminSession.save(); - } catch (RepositoryException e) { - JcrUtils.discardQuietly(adminSession); - throw new JcrException("Cannot sync node security model for " + username, e); - } - } - - /** Generate path for a new user home */ - private String generateUserPath(String username) { - LdapName dn; - try { - dn = new LdapName(username); - } catch (InvalidNameException e) { - throw new IllegalArgumentException("Invalid name " + username, e); - } - String userId = dn.getRdn(dn.size() - 1).getValue().toString(); - return '/' + userId; -// int atIndex = userId.indexOf('@'); -// if (atIndex < 0) { -// return homeBasePath+'/' + userId; -// } else { -// return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId; -// } - } - - private String extractUserId(String username) { - LdapName dn; - try { - dn = new LdapName(username); - } catch (InvalidNameException e) { - throw new IllegalArgumentException("Invalid name " + username, e); - } - String userId = dn.getRdn(dn.size() - 1).getValue().toString(); - return userId; -// int atIndex = userId.indexOf('@'); -// if (atIndex < 0) { -// return homeBasePath+'/' + userId; -// } else { -// return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId; -// } - } - - public void createWorkgroup(LdapName dn) { - String groupsWorkspace = getGroupsWorkspace(); - Session adminSession = KernelUtils.openAdminSession(getRepository(groupsWorkspace), groupsWorkspace); - String cn = dn.getRdn(dn.size() - 1).getValue().toString(); - Node newWorkgroup = CmsJcrUtils.getGroupHome(adminSession, cn); - if (newWorkgroup != null) { - JcrUtils.logoutQuietly(adminSession); - throw new IllegalStateException("Workgroup " + newWorkgroup + " already exists for " + dn); - } - try { - // TODO enhance transformation of cn to a valid node name - // String relPath = cn.replaceAll("[^a-zA-Z0-9]", "_"); - String relPath = JcrUtils.replaceInvalidChars(cn); - newWorkgroup = adminSession.getRootNode().addNode(relPath, NodeType.NT_UNSTRUCTURED); -// newWorkgroup = JcrUtils.mkdirs(adminSession.getNode(groupsBasePath), relPath, NodeType.NT_UNSTRUCTURED); -// newWorkgroup.addMixin(NodeTypes.NODE_GROUP_HOME); - newWorkgroup.addMixin(NodeType.MIX_CREATED); - newWorkgroup.addMixin(NodeType.MIX_TITLE); - newWorkgroup.setProperty(Property.JCR_ID, dn.toString()); - newWorkgroup.setProperty(Property.JCR_TITLE, cn); -// newWorkgroup.setProperty(NodeNames.LDAP_CN, cn); - adminSession.save(); - JcrUtils.addPrivilege(adminSession, newWorkgroup.getPath(), dn.toString(), Privilege.JCR_ALL); - adminSession.save(); - } catch (RepositoryException e) { - throw new JcrException("Cannot create workgroup", e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - - } - - public boolean isRemote() { - return remote; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JackrabbitLocalRepository.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JackrabbitLocalRepository.java deleted file mode 100644 index bad9fdfd5..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JackrabbitLocalRepository.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.jackrabbit.core.RepositoryImpl; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; - -class JackrabbitLocalRepository extends LocalRepository { - private final static CmsLog log = CmsLog.getLog(JackrabbitLocalRepository.class); - final String SECURITY_WORKSPACE = "security"; - - private Map workspaceMonitors = new TreeMap<>(); - - public JackrabbitLocalRepository(RepositoryImpl repository, String cn) { - super(repository, cn); -// Session session = KernelUtils.openAdminSession(repository); -// try { -// if (NodeConstants.NODE.equals(cn)) -// for (String workspaceName : session.getWorkspace().getAccessibleWorkspaceNames()) { -// addMonitor(workspaceName); -// } -// } catch (RepositoryException e) { -// throw new IllegalStateException(e); -// } finally { -// JcrUtils.logoutQuietly(session); -// } - } - - protected RepositoryImpl getJackrabbitrepository(String workspaceName) { - return (RepositoryImpl) getRepository(workspaceName); - } - - @Override - protected synchronized void processNewSession(Session session, String workspaceName) { -// String realWorkspaceName = session.getWorkspace().getName(); -// addMonitor(realWorkspaceName); - } - - private void addMonitor(String realWorkspaceName) { - if (realWorkspaceName.equals(SECURITY_WORKSPACE)) - return; - if (!CmsConstants.NODE_REPOSITORY.equals(getCn())) - return; - - if (!workspaceMonitors.containsKey(realWorkspaceName)) { - try { - CmsWorkspaceIndexer workspaceMonitor = new CmsWorkspaceIndexer( - getJackrabbitrepository(realWorkspaceName), getCn(), realWorkspaceName); - workspaceMonitors.put(realWorkspaceName, workspaceMonitor); - workspaceMonitor.init(); - if (log.isDebugEnabled()) - log.debug("Registered " + workspaceMonitor); - } catch (RepositoryException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - public void destroy() { - for (String workspaceName : workspaceMonitors.keySet()) { - workspaceMonitors.get(workspaceName).destroy(); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrKeyring.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrKeyring.java deleted file mode 100644 index 17625f5d2..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrKeyring.java +++ /dev/null @@ -1,397 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; - -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; - -import org.apache.commons.io.IOUtils; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.ArgeoNames; -import org.argeo.cms.ArgeoTypes; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.security.AbstractKeyring; -import org.argeo.cms.security.PBEKeySpecCallback; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** JCR based implementation of a keyring */ -public class JcrKeyring extends AbstractKeyring implements ArgeoNames { - private final static CmsLog log = CmsLog.getLog(JcrKeyring.class); - /** - * Stronger with 256, but causes problem with Oracle JVM, force 128 in this case - */ - public final static Long DEFAULT_SECRETE_KEY_LENGTH = 256l; - public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1"; - public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES"; - public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding"; - - private Integer iterationCountFactor = 200; - private Long secretKeyLength = DEFAULT_SECRETE_KEY_LENGTH; - private String secretKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY; - private String secretKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION; - private String cipherName = DEFAULT_CIPHER_NAME; - - private final Repository repository; - // TODO remove thread local session ; open a session each time - private ThreadLocal sessionThreadLocal = new ThreadLocal() { - - @Override - protected Session initialValue() { - return login(); - } - - }; - - // FIXME is it really still needed? - /** - * When setup is called the session has not yet been saved and we don't want to - * save it since there maybe other data which would be inconsistent. So we keep - * a reference to this node which will then be used (an reset to null) when - * handling the PBE callback. We keep one per thread in case multiple users are - * accessing the same instance of a keyring. - */ - // private ThreadLocal notYetSavedKeyring = new ThreadLocal() { - // - // @Override - // protected Node initialValue() { - // return null; - // } - // }; - - public JcrKeyring(Repository repository) { - this.repository = repository; - } - - private Session session() { - Session session = this.sessionThreadLocal.get(); - if (!session.isLive()) { - session = login(); - sessionThreadLocal.set(session); - } - return session; - } - - private Session login() { - try { - return repository.login(CmsConstants.HOME_WORKSPACE); - } catch (RepositoryException e) { - throw new JcrException("Cannot login key ring session", e); - } - } - - @Override - protected synchronized Boolean isSetup() { - Session session = null; - try { - // if (notYetSavedKeyring.get() != null) - // return true; - session = session(); - session.refresh(true); - Node userHome = CmsJcrUtils.getUserHome(session); - return userHome.hasNode(ARGEO_KEYRING); - } catch (RepositoryException e) { - throw new JcrException("Cannot check whether keyring is setup", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - @Override - protected synchronized void setup(char[] password) { - Binary binary = null; - // InputStream in = null; - try { - session().refresh(true); - Node userHome = CmsJcrUtils.getUserHome(session()); - Node keyring; - if (userHome.hasNode(ARGEO_KEYRING)) { - throw new IllegalArgumentException("Keyring already set up"); - } else { - keyring = userHome.addNode(ARGEO_KEYRING); - } - keyring.addMixin(ArgeoTypes.ARGEO_PBE_SPEC); - - // deterministic salt and iteration count based on username - String username = session().getUserID(); - byte[] salt = new byte[8]; - byte[] usernameBytes = username.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < salt.length; i++) { - if (i < usernameBytes.length) - salt[i] = usernameBytes[i]; - else - salt[i] = 0; - } - try (InputStream in = new ByteArrayInputStream(salt);) { - binary = session().getValueFactory().createBinary(in); - keyring.setProperty(ARGEO_SALT, binary); - } catch (IOException e) { - throw new RuntimeException("Cannot set keyring salt", e); - } - - Integer iterationCount = username.length() * iterationCountFactor; - keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); - - // default algo - // TODO check if algo and key length are available, use DES if not - keyring.setProperty(ARGEO_SECRET_KEY_FACTORY, secretKeyFactoryName); - keyring.setProperty(ARGEO_KEY_LENGTH, secretKeyLength); - keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, secretKeyEncryption); - keyring.setProperty(ARGEO_CIPHER, cipherName); - - keyring.getSession().save(); - - // encrypted password hash - // IOUtils.closeQuietly(in); - // JcrUtils.closeQuietly(binary); - // byte[] btPass = hash(password, salt, iterationCount); - // in = new ByteArrayInputStream(btPass); - // binary = session().getValueFactory().createBinary(in); - // keyring.setProperty(ARGEO_PASSWORD, binary); - - // notYetSavedKeyring.set(keyring); - } catch (RepositoryException e) { - throw new JcrException("Cannot setup keyring", e); - } finally { - JcrUtils.closeQuietly(binary); - // IOUtils.closeQuietly(in); - // JcrUtils.discardQuietly(session()); - } - } - - @Override - protected synchronized void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { - Session session = null; - try { - session = session(); - session.refresh(true); - Node userHome = CmsJcrUtils.getUserHome(session); - Node keyring; - if (userHome.hasNode(ARGEO_KEYRING)) - keyring = userHome.getNode(ARGEO_KEYRING); - // else if (notYetSavedKeyring.get() != null) - // keyring = notYetSavedKeyring.get(); - else - throw new IllegalStateException("Keyring not setup"); - - pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY).getString(), - JcrUtils.getBinaryAsBytes(keyring.getProperty(ARGEO_SALT)), - (int) keyring.getProperty(ARGEO_ITERATION_COUNT).getLong(), - (int) keyring.getProperty(ARGEO_KEY_LENGTH).getLong(), - keyring.getProperty(ARGEO_SECRET_KEY_ENCRYPTION).getString()); - - // if (notYetSavedKeyring.get() != null) - // notYetSavedKeyring.remove(); - } catch (RepositoryException e) { - throw new JcrException("Cannot handle key spec callback", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - /** The parent node must already exist at this path. */ - @Override - protected synchronized void encrypt(String path, InputStream unencrypted) { - // should be called first for lazy initialization - SecretKey secretKey = getSecretKey(null); - Cipher cipher = createCipher(); - - // Binary binary = null; - // InputStream in = null; - try { - session().refresh(true); - Node node; - if (!session().nodeExists(path)) { - String parentPath = JcrUtils.parentPath(path); - if (!session().nodeExists(parentPath)) - throw new IllegalStateException("No parent node of " + path); - Node parentNode = session().getNode(parentPath); - node = parentNode.addNode(JcrUtils.nodeNameFromPath(path)); - } else { - node = session().getNode(path); - } - encrypt(secretKey, cipher, node, unencrypted); - // node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); - // SecureRandom random = new SecureRandom(); - // byte[] iv = new byte[16]; - // random.nextBytes(iv); - // cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); - // JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); - // - // try (InputStream in = new CipherInputStream(unencrypted, cipher);) { - // binary = session().getValueFactory().createBinary(in); - // node.setProperty(Property.JCR_DATA, binary); - // session().save(); - // } - } catch (RepositoryException e) { - throw new JcrException("Cannot encrypt", e); - } finally { - try { - unencrypted.close(); - } catch (IOException e) { - // silent - } - // IOUtils.closeQuietly(unencrypted); - // IOUtils.closeQuietly(in); - // JcrUtils.closeQuietly(binary); - JcrUtils.logoutQuietly(session()); - } - } - - protected synchronized void encrypt(SecretKey secretKey, Cipher cipher, Node node, InputStream unencrypted) { - try { - node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); - SecureRandom random = new SecureRandom(); - byte[] iv = new byte[16]; - random.nextBytes(iv); - cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); - JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); - - Binary binary = null; - try (InputStream in = new CipherInputStream(unencrypted, cipher);) { - binary = session().getValueFactory().createBinary(in); - node.setProperty(Property.JCR_DATA, binary); - session().save(); - } finally { - JcrUtils.closeQuietly(binary); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot encrypt", e); - } catch (GeneralSecurityException | IOException e) { - throw new RuntimeException("Cannot encrypt", e); - } - } - - @Override - protected synchronized InputStream decrypt(String path) { - Binary binary = null; - try { - session().refresh(true); - if (!session().nodeExists(path)) { - char[] password = ask(); - Reader reader = new CharArrayReader(password); - return new ByteArrayInputStream(IOUtils.toByteArray(reader, StandardCharsets.UTF_8)); - } else { - // should be called first for lazy initialisation - SecretKey secretKey = getSecretKey(null); - Cipher cipher = createCipher(); - Node node = session().getNode(path); - return decrypt(secretKey, cipher, node); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot decrypt", e); - } catch (GeneralSecurityException | IOException e) { - throw new RuntimeException("Cannot decrypt", e); - } finally { - JcrUtils.closeQuietly(binary); - JcrUtils.logoutQuietly(session()); - } - } - - protected synchronized InputStream decrypt(SecretKey secretKey, Cipher cipher, Node node) - throws RepositoryException, GeneralSecurityException { - if (node.hasProperty(ARGEO_IV)) { - byte[] iv = JcrUtils.getBinaryAsBytes(node.getProperty(ARGEO_IV)); - cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); - } else { - cipher.init(Cipher.DECRYPT_MODE, secretKey); - } - - Binary binary = node.getProperty(Property.JCR_DATA).getBinary(); - InputStream encrypted = binary.getStream(); - return new CipherInputStream(encrypted, cipher); - } - - protected Cipher createCipher() { - try { - Node userHome = CmsJcrUtils.getUserHome(session()); - if (!userHome.hasNode(ARGEO_KEYRING)) - throw new IllegalArgumentException("Keyring not setup"); - Node keyring = userHome.getNode(ARGEO_KEYRING); - String cipherName = keyring.getProperty(ARGEO_CIPHER).getString(); - Provider securityProvider = getSecurityProvider(); - Cipher cipher; - if (securityProvider == null)// TODO use BC? - cipher = Cipher.getInstance(cipherName); - else - cipher = Cipher.getInstance(cipherName, securityProvider); - return cipher; - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - throw new IllegalArgumentException("Cannot get cipher", e); - } catch (RepositoryException e) { - throw new JcrException("Cannot get cipher", e); - } finally { - - } - } - - public synchronized void changePassword(char[] oldPassword, char[] newPassword) { - // TODO make it XA compatible - SecretKey oldSecretKey = getSecretKey(oldPassword); - SecretKey newSecretKey = getSecretKey(newPassword); - Session session = session(); - try { - NodeIterator encryptedNodes = session.getWorkspace().getQueryManager() - .createQuery("select * from [argeo:encrypted]", Query.JCR_SQL2).execute().getNodes(); - while (encryptedNodes.hasNext()) { - Node node = encryptedNodes.nextNode(); - InputStream in = decrypt(oldSecretKey, createCipher(), node); - encrypt(newSecretKey, createCipher(), node, in); - if (log.isDebugEnabled()) - log.debug("Converted keyring encrypted value of " + node.getPath()); - } - } catch (GeneralSecurityException e) { - throw new RuntimeException("Cannot change JCR keyring password", e); - } catch (RepositoryException e) { - throw new JcrException("Cannot change JCR keyring password", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - // public synchronized void setSession(Session session) { - // this.session = session; - // } - - public void setIterationCountFactor(Integer iterationCountFactor) { - this.iterationCountFactor = iterationCountFactor; - } - - public void setSecretKeyLength(Long keyLength) { - this.secretKeyLength = keyLength; - } - - public void setSecretKeyFactoryName(String secreteKeyFactoryName) { - this.secretKeyFactoryName = secreteKeyFactoryName; - } - - public void setSecretKeyEncryption(String secreteKeyEncryption) { - this.secretKeyEncryption = secreteKeyEncryption; - } - - public void setCipherName(String cipherName) { - this.cipherName = cipherName; - } - -} \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrRepositoryFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrRepositoryFactory.java deleted file mode 100644 index 342c1add7..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrRepositoryFactory.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.internal.jcr.RepoConf; -import org.argeo.cms.jcr.internal.osgi.CmsJcrActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; - -/** - * OSGi-aware Jackrabbit repository factory which can retrieve/publish - * {@link Repository} as OSGi services. - */ -public class JcrRepositoryFactory implements RepositoryFactory { - private final CmsLog log = CmsLog.getLog(getClass()); -// private final BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - // private Resource fileRepositoryConfiguration = new ClassPathResource( - // "/org/argeo/cms/internal/kernel/repository-localfs.xml"); - - protected Repository getRepositoryByAlias(String alias) { - BundleContext bundleContext = CmsJcrActivator.getBundleContext(); - if (bundleContext != null) { - try { - Collection> srs = bundleContext.getServiceReferences(Repository.class, - "(" + CmsConstants.CN + "=" + alias + ")"); - if (srs.size() == 0) - throw new IllegalArgumentException("No repository with alias " + alias + " found in OSGi registry"); - else if (srs.size() > 1) - throw new IllegalArgumentException( - srs.size() + " repositories with alias " + alias + " found in OSGi registry"); - return bundleContext.getService(srs.iterator().next()); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot find repository with alias " + alias, e); - } - } else { - // TODO ability to filter static services - return null; - } - } - - // private void publish(String alias, Repository repository, Properties - // properties) { - // if (bundleContext != null) { - // // do not modify reference - // Hashtable props = new Hashtable(); - // props.putAll(props); - // props.put(JCR_REPOSITORY_ALIAS, alias); - // bundleContext.registerService(Repository.class.getName(), repository, - // props); - // } - // } - - @SuppressWarnings({ "rawtypes" }) - public Repository getRepository(Map parameters) throws RepositoryException { - // // check if can be found by alias - // Repository repository = super.getRepository(parameters); - // if (repository != null) - // return repository; - - // check if remote - Repository repository; - String uri = null; - if (parameters.containsKey(RepoConf.labeledUri.name())) - uri = parameters.get(CmsConstants.LABELED_URI).toString(); - else if (parameters.containsKey(KernelConstants.JACKRABBIT_REPOSITORY_URI)) - uri = parameters.get(KernelConstants.JACKRABBIT_REPOSITORY_URI).toString(); - - if (uri != null) { - if (uri.startsWith("http")) {// http, https - Object defaultWorkspace = parameters.get(RepoConf.defaultWorkspace.name()); - repository = createRemoteRepository(uri, defaultWorkspace != null ? defaultWorkspace.toString() : null); - } else if (uri.startsWith("file"))// http, https - repository = createFileRepository(uri, parameters); - else if (uri.startsWith("vm")) { - // log.warn("URI " + uri + " should have been managed by generic - // JCR repository factory"); - repository = getRepositoryByAlias(getAliasFromURI(uri)); - } else - throw new IllegalArgumentException("Unrecognized URI format " + uri); - - } - - else if (parameters.containsKey(CmsConstants.CN)) { - // Properties properties = new Properties(); - // properties.putAll(parameters); - String alias = parameters.get(CmsConstants.CN).toString(); - // publish(alias, repository, properties); - // log.info("Registered JCR repository under alias '" + alias + "' - // with properties " + properties); - repository = getRepositoryByAlias(alias); - } else - throw new IllegalArgumentException("Not enough information in " + parameters); - - if (repository == null) - throw new IllegalArgumentException("Repository not found " + parameters); - - return repository; - } - - protected Repository createRemoteRepository(String uri, String defaultWorkspace) throws RepositoryException { - Map params = new HashMap(); - params.put(KernelConstants.JACKRABBIT_REPOSITORY_URI, uri); - if (defaultWorkspace != null) - params.put(KernelConstants.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, defaultWorkspace); - Repository repository = new Jcr2davRepositoryFactory().getRepository(params); - if (repository == null) - throw new IllegalArgumentException("Remote Davex repository " + uri + " not found"); - log.info("Initialized remote Jackrabbit repository from uri " + uri); - return repository; - } - - @SuppressWarnings({ "rawtypes" }) - protected Repository createFileRepository(final String uri, Map parameters) throws RepositoryException { - throw new UnsupportedOperationException(); - // InputStream configurationIn = null; - // try { - // Properties vars = new Properties(); - // vars.putAll(parameters); - // String dirPath = uri.substring("file:".length()); - // File homeDir = new File(dirPath); - // if (homeDir.exists() && !homeDir.isDirectory()) - // throw new ArgeoJcrException("Repository home " + dirPath + " is not a - // directory"); - // if (!homeDir.exists()) - // homeDir.mkdirs(); - // configurationIn = fileRepositoryConfiguration.getInputStream(); - // vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, - // homeDir.getCanonicalPath()); - // RepositoryConfig repositoryConfig = RepositoryConfig.create(new - // InputSource(configurationIn), vars); - // - // // TransientRepository repository = new - // // TransientRepository(repositoryConfig); - // final RepositoryImpl repository = - // RepositoryImpl.create(repositoryConfig); - // Session session = repository.login(); - // // FIXME make it generic - // org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN", - // "jcr:all"); - // org.argeo.jcr.JcrUtils.logoutQuietly(session); - // Runtime.getRuntime().addShutdownHook(new Thread("Clean JCR repository - // " + uri) { - // public void run() { - // repository.shutdown(); - // log.info("Destroyed repository " + uri); - // } - // }); - // log.info("Initialized file Jackrabbit repository from uri " + uri); - // return repository; - // } catch (Exception e) { - // throw new ArgeoJcrException("Cannot create repository " + uri, e); - // } finally { - // IOUtils.closeQuietly(configurationIn); - // } - } - - protected String getAliasFromURI(String uri) { - try { - URI uriObj = new URI(uri); - String alias = uriObj.getPath(); - if (alias.charAt(0) == '/') - alias = alias.substring(1); - if (alias.charAt(alias.length() - 1) == '/') - alias = alias.substring(0, alias.length() - 1); - return alias; - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Cannot interpret URI " + uri, e); - } - } - - /** - * Called after the repository has been initialised. Does nothing by default. - */ - @SuppressWarnings("rawtypes") - protected void postInitialization(Repository repository, Map parameters) { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelConstants.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelConstants.java deleted file mode 100644 index 93f29fbe8..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelConstants.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import org.argeo.api.cms.CmsConstants; - -/** Internal CMS constants. */ -@Deprecated -public interface KernelConstants { - // Directories - String DIR_NODE = "node"; - String DIR_REPOS = "repos"; - String DIR_INDEXES = "indexes"; - String DIR_TRANSACTIONS = "transactions"; - - // Files - String DEPLOY_CONFIG_PATH = DIR_NODE + '/' + CmsConstants.DEPLOY_BASEDN + ".ldif"; - String DEFAULT_KEYSTORE_PATH = DIR_NODE + '/' + CmsConstants.NODE + ".p12"; - String DEFAULT_PEM_KEY_PATH = DIR_NODE + '/' + CmsConstants.NODE + ".key"; - String DEFAULT_PEM_CERT_PATH = DIR_NODE + '/' + CmsConstants.NODE + ".crt"; - String NODE_KEY_TAB_PATH = DIR_NODE + "/krb5.keytab"; - - // Security - String JAAS_CONFIG = "/org/argeo/cms/internal/kernel/jaas.cfg"; - String JAAS_CONFIG_IPA = "/org/argeo/cms/internal/kernel/jaas-ipa.cfg"; - - // Java - String JAAS_CONFIG_PROP = "java.security.auth.login.config"; - - // DEFAULTS JCR PATH - String DEFAULT_HOME_BASE_PATH = "/home"; - String DEFAULT_USERS_BASE_PATH = "/users"; - String DEFAULT_GROUPS_BASE_PATH = "/groups"; - - // KERBEROS - String DEFAULT_KERBEROS_SERVICE = "HTTP"; - - // HTTP client - String COOKIE_POLICY_BROWSER_COMPATIBILITY = "compatibility"; - - // RWT / RAP - // String PATH_WORKBENCH = "/ui"; - // String PATH_WORKBENCH_PUBLIC = PATH_WORKBENCH + "/public"; - - String JETTY_FACTORY_PID = "org.eclipse.equinox.http.jetty.config"; - String WHITEBOARD_PATTERN_PROP = "osgi.http.whiteboard.servlet.pattern"; - // default Jetty server configured via JettyConfigurator - String DEFAULT_JETTY_SERVER = "default"; - String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer"; - - // avoid dependencies - String CONTEXT_NAME_PROP = "contextName"; - String JACKRABBIT_REPOSITORY_URI = "org.apache.jackrabbit.repository.uri"; - String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "org.apache.jackrabbit.spi2davex.WorkspaceNameDefault"; -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelUtils.java deleted file mode 100644 index edfe87a03..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelUtils.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.PrivilegedAction; -import java.security.URIParameter; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.Properties; -import java.util.TreeMap; -import java.util.TreeSet; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -import org.argeo.api.cms.CmsAuth; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.jcr.internal.osgi.CmsJcrActivator; -import org.argeo.cms.osgi.DataModelNamespace; -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; - -/** Package utilities */ -class KernelUtils implements KernelConstants { - final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; - final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; - - static void setJaasConfiguration(URL jaasConfigurationUrl) { - try { - URIParameter uriParameter = new URIParameter(jaasConfigurationUrl.toURI()); - javax.security.auth.login.Configuration jaasConfiguration = javax.security.auth.login.Configuration - .getInstance("JavaLoginConfig", uriParameter); - javax.security.auth.login.Configuration.setConfiguration(jaasConfiguration); - } catch (Exception e) { - throw new IllegalArgumentException("Cannot set configuration " + jaasConfigurationUrl, e); - } - } - - static Dictionary asDictionary(Properties props) { - Hashtable hashtable = new Hashtable(); - for (Object key : props.keySet()) { - hashtable.put(key.toString(), props.get(key)); - } - return hashtable; - } - - static Dictionary asDictionary(ClassLoader cl, String resource) { - Properties props = new Properties(); - try { - props.load(cl.getResourceAsStream(resource)); - } catch (IOException e) { - throw new IllegalArgumentException("Cannot load " + resource + " from classpath", e); - } - return asDictionary(props); - } - - static File getExecutionDir(String relativePath) { - File executionDir = new File(getFrameworkProp("user.dir")); - if (relativePath == null) - return executionDir; - try { - return new File(executionDir, relativePath).getCanonicalFile(); - } catch (IOException e) { - throw new IllegalArgumentException("Cannot get canonical file", e); - } - } - - static File getOsgiInstanceDir() { - return new File(getBundleContext().getProperty(OSGI_INSTANCE_AREA).substring("file:".length())) - .getAbsoluteFile(); - } - - static Path getOsgiInstancePath(String relativePath) { - return Paths.get(getOsgiInstanceUri(relativePath)); - } - - static URI getOsgiInstanceUri(String relativePath) { - String osgiInstanceBaseUri = getFrameworkProp(OSGI_INSTANCE_AREA); - if (osgiInstanceBaseUri != null) - return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : "")); - else - return Paths.get(System.getProperty("user.dir")).toUri(); - } - - static File getOsgiConfigurationFile(String relativePath) { - try { - return new File(new URI(getBundleContext().getProperty(OSGI_CONFIGURATION_AREA) + relativePath)) - .getCanonicalFile(); - } catch (Exception e) { - throw new IllegalArgumentException("Cannot get configuration file for " + relativePath, e); - } - } - - static String getFrameworkProp(String key, String def) { - BundleContext bundleContext = CmsJcrActivator.getBundleContext(); - String value; - if (bundleContext != null) - value = bundleContext.getProperty(key); - else - value = System.getProperty(key); - if (value == null) - return def; - return value; - } - - static String getFrameworkProp(String key) { - return getFrameworkProp(key, null); - } - - // Security - // static Subject anonymousLogin() { - // Subject subject = new Subject(); - // LoginContext lc; - // try { - // lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject); - // lc.login(); - // return subject; - // } catch (LoginException e) { - // throw new CmsException("Cannot login as anonymous", e); - // } - // } - - static void logFrameworkProperties(CmsLog log) { - BundleContext bc = getBundleContext(); - for (Object sysProp : new TreeSet(System.getProperties().keySet())) { - log.debug(sysProp + "=" + bc.getProperty(sysProp.toString())); - } - // String[] keys = { Constants.FRAMEWORK_STORAGE, - // Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION, - // Constants.FRAMEWORK_PROCESSOR, Constants.FRAMEWORK_SECURITY, - // Constants.FRAMEWORK_TRUST_REPOSITORIES, - // Constants.FRAMEWORK_WINDOWSYSTEM, Constants.FRAMEWORK_VENDOR, - // Constants.FRAMEWORK_VERSION, Constants.FRAMEWORK_STORAGE_CLEAN, - // Constants.FRAMEWORK_LANGUAGE, Constants.FRAMEWORK_UUID }; - // for (String key : keys) - // log.debug(key + "=" + bc.getProperty(key)); - } - - static void printSystemProperties(PrintStream out) { - TreeMap display = new TreeMap<>(); - for (Object key : System.getProperties().keySet()) - display.put(key.toString(), System.getProperty(key.toString())); - for (String key : display.keySet()) - out.println(key + "=" + display.get(key)); - } - - static Session openAdminSession(Repository repository) { - return openAdminSession(repository, null); - } - - static Session openAdminSession(final Repository repository, final String workspaceName) { - LoginContext loginContext = loginAsDataAdmin(); - return Subject.doAs(loginContext.getSubject(), new PrivilegedAction() { - - @Override - public Session run() { - try { - return repository.login(workspaceName); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot open admin session", e); - } finally { - try { - loginContext.logout(); - } catch (LoginException e) { - throw new IllegalStateException(e); - } - } - } - - }); - } - - static LoginContext loginAsDataAdmin() { - ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(KernelUtils.class.getClassLoader()); - LoginContext loginContext; - try { - loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_DATA_ADMIN); - loginContext.login(); - } catch (LoginException e1) { - throw new IllegalStateException("Could not login as data admin", e1); - } finally { - Thread.currentThread().setContextClassLoader(currentCl); - } - return loginContext; - } - - static void doAsDataAdmin(Runnable action) { - LoginContext loginContext = loginAsDataAdmin(); - Subject.doAs(loginContext.getSubject(), new PrivilegedAction() { - - @Override - public Void run() { - try { - action.run(); - return null; - } finally { - try { - loginContext.logout(); - } catch (LoginException e) { - throw new IllegalStateException(e); - } - } - } - - }); - } - - static void asyncOpen(ServiceTracker st) { - Runnable run = new Runnable() { - - @Override - public void run() { - st.open(); - } - }; -// Activator.getInternalExecutorService().execute(run); - new Thread(run, "Open service tracker " + st).start(); - } - - static BundleContext getBundleContext() { - return CmsJcrActivator.getBundleContext(); - } - - static boolean asBoolean(String value) { - if (value == null) - return false; - switch (value) { - case "true": - return true; - case "false": - return false; - default: - throw new IllegalArgumentException( - "Unsupported value for attribute " + DataModelNamespace.ABSTRACT + ": " + value); - } - } - - private static URI safeUri(String uri) { - if (uri == null) - throw new IllegalArgumentException("URI cannot be null"); - try { - return new URI(uri); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Badly formatted URI " + uri, e); - } - } - - private KernelUtils() { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/LocalRepository.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/LocalRepository.java deleted file mode 100644 index 0bac94cc0..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/LocalRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import javax.jcr.Repository; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.jcr.JcrRepositoryWrapper; - -class LocalRepository extends JcrRepositoryWrapper { - private final String cn; - - public LocalRepository(Repository repository, String cn) { - super(repository); - this.cn = cn; - // Map attrs = dataModelCapability.getAttributes(); - // cn = (String) attrs.get(DataModelNamespace.NAME); - putDescriptor(CmsConstants.CN, cn); - } - - String getCn() { - return cn; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/NodeKeyRing.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/NodeKeyRing.java deleted file mode 100644 index 9cd1f7269..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/NodeKeyRing.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.util.Dictionary; - -import javax.jcr.Repository; - -import org.osgi.service.cm.ConfigurationException; -import org.osgi.service.cm.ManagedService; - -class NodeKeyRing extends JcrKeyring implements ManagedService{ - - public NodeKeyRing(Repository repository) { - super(repository); - } - - @Override - public void updated(Dictionary properties) throws ConfigurationException { - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java deleted file mode 100644 index f3a099b08..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.apache.jackrabbit.core.RepositoryContext; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsState; -import org.argeo.cms.CmsDeployProperty; -import org.argeo.cms.internal.jcr.RepoConf; -import org.argeo.cms.internal.jcr.RepositoryBuilder; -import org.argeo.cms.jcr.internal.osgi.CmsJcrActivator; -import org.argeo.util.LangUtils; -import org.osgi.service.cm.ManagedServiceFactory; - -/** A {@link ManagedServiceFactory} creating or referencing JCR repositories. */ -public class RepositoryContextsFactory { - private final static CmsLog log = CmsLog.getLog(RepositoryContextsFactory.class); - private final static String NODE_REPO_PROP_PREFIX = "argeo.node.repo."; -// private final BundleContext bc = FrameworkUtil.getBundle(RepositoryServiceFactory.class).getBundleContext(); - -// private Map repositories = new HashMap(); -// private Map pidToCn = new HashMap(); - - private RepositoryContext repositoryContext; - - private CmsState cmsState; - - public void init() { - Dictionary config = getNodeRepositoryConfig(); - deployRepository(config); - } - - public void destroy() { - if (this.repositoryContext != null) { - this.repositoryContext.getRepository().shutdown(); - } -// for (String pid : repositories.keySet()) { -// try { -// RepositoryContext repositoryContext = repositories.get(pid); -// // Must start in another thread otherwise shutdown is interrupted -// // TODO use an executor? -// new Thread(() -> { -// repositoryContext.getRepository().shutdown(); -// if (log.isDebugEnabled()) -// log.debug("Shut down repository " + pid -// + (pidToCn.containsKey(pid) ? " (" + pidToCn.get(pid) + ")" : "")); -// }, "Shutdown JCR repository " + pid).start(); -// } catch (Exception e) { -// log.error("Error when shutting down Jackrabbit repository " + pid, e); -// } -// } - } - -// @Override -// public String getName() { -// return "Jackrabbit repository service factory"; -// } - - /** Override the provided config with the framework properties */ - private Dictionary getNodeRepositoryConfig() { - Dictionary props = new Hashtable(); - addDeployProperty(CmsDeployProperty.DB_URL, RepoConf.dburl, props); - addDeployProperty(CmsDeployProperty.DB_USER, RepoConf.dbuser, props); - addDeployProperty(CmsDeployProperty.DB_PASSWORD, RepoConf.dbpassword, props); - for (RepoConf repoConf : RepoConf.values()) { - Object value = getFrameworkProp(NODE_REPO_PROP_PREFIX + repoConf.name()); - if (value != null) { - props.put(repoConf.name(), value); - if (log.isDebugEnabled()) - log.debug("Set node repo configuration " + repoConf.name() + " to " + value); - } - } - props.put(CmsConstants.CN, CmsConstants.NODE_REPOSITORY); - return props; - } - - private void addDeployProperty(CmsDeployProperty deployProperty, RepoConf repoConf, - Dictionary props) { - String value = getFrameworkProp(deployProperty.getProperty()); - if (value != null) { - props.put(repoConf.name(), value); - } - - } - -// @Override -// public void updated(String pid, Dictionary properties) throws ConfigurationException { - protected void deployRepository(Dictionary properties) { -// if (repositories.containsKey(pid)) -// throw new IllegalArgumentException("Already a repository registered for " + pid); - - if (properties == null) - return; - - Object cn = properties.get(CmsConstants.CN); -// if (cn != null) -// for (String otherPid : pidToCn.keySet()) { -// Object o = pidToCn.get(otherPid); -// if (cn.equals(o)) { -// RepositoryContext repositoryContext = repositories.remove(otherPid); -// repositories.put(pid, repositoryContext); -// if (log.isDebugEnabled()) -// log.debug("Ignoring update of Jackrabbit repository " + cn); -// // FIXME perform a proper update (also of the OSGi service) -// return; -// } -// } - - try { - Object labeledUri = properties.get(RepoConf.labeledUri.name()); - if (labeledUri == null) { - RepositoryBuilder repositoryBuilder = new RepositoryBuilder(); - RepositoryContext repositoryContext = repositoryBuilder.createRepositoryContext(properties); -// repositories.put(pid, repositoryContext); -// Dictionary props = LangUtils.dict(Constants.SERVICE_PID, pid); - Dictionary props = new Hashtable<>(); - // props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, - // properties.get(RepoConf.labeledUri.name())); - if (cn != null) { - props.put(CmsConstants.CN, cn); - // props.put(NodeConstants.JCR_REPOSITORY_ALIAS, cn); -// pidToCn.put(pid, cn); - } - CmsJcrActivator.registerService(RepositoryContext.class, repositoryContext, props); - this.repositoryContext = repositoryContext; - } else { - Object defaultWorkspace = properties.get(RepoConf.defaultWorkspace.name()); - if (defaultWorkspace == null) - defaultWorkspace = RepoConf.defaultWorkspace.getDefault(); - URI uri = new URI(labeledUri.toString()); -// RepositoryFactory repositoryFactory = bc -// .getService(bc.getServiceReference(RepositoryFactory.class)); - RepositoryFactory repositoryFactory = CmsJcrActivator.getService(RepositoryFactory.class); - Map parameters = new HashMap(); - parameters.put(RepoConf.labeledUri.name(), uri.toString()); - parameters.put(RepoConf.defaultWorkspace.name(), defaultWorkspace.toString()); - Repository repository = repositoryFactory.getRepository(parameters); - // Repository repository = NodeUtils.getRepositoryByUri(repositoryFactory, - // uri.toString()); -// Dictionary props = LangUtils.dict(Constants.SERVICE_PID, pid); - Dictionary props = new Hashtable<>(); - props.put(RepoConf.labeledUri.name(), - new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), null, null) - .toString()); - if (cn != null) { - props.put(CmsConstants.CN, cn); -// pidToCn.put(pid, cn); - } - CmsJcrActivator.registerService(Repository.class, repository, props); - - // home - if (cn.equals(CmsConstants.NODE_REPOSITORY)) { - Dictionary homeProps = LangUtils.dict(CmsConstants.CN, CmsConstants.EGO_REPOSITORY); - EgoRepository homeRepository = new EgoRepository(repository, true); - CmsJcrActivator.registerService(Repository.class, homeRepository, homeProps); - } - } - } catch (RepositoryException | URISyntaxException | IOException e) { - throw new IllegalStateException("Cannot create Jackrabbit repository " + properties, e); - } - - } - -// @Override -// public void deleted(String pid) { -// RepositoryContext repositoryContext = repositories.remove(pid); -// repositoryContext.getRepository().shutdown(); -// if (log.isDebugEnabled()) -// log.debug("Deleted repository " + pid); -// } - - private String getFrameworkProp(String key) { - return cmsState.getDeployProperty(key); - } - - public void setCmsState(CmsState cmsState) { - this.cmsState = cmsState; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/StatisticsThread.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/StatisticsThread.java deleted file mode 100644 index 5a2cd5b7b..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/StatisticsThread.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.argeo.cms.jcr.internal; - -import java.io.File; -import java.lang.management.ManagementFactory; - -import org.apache.jackrabbit.api.stats.RepositoryStatistics; -import org.apache.jackrabbit.stats.RepositoryStatisticsImpl; -import org.argeo.api.cms.CmsLog; - -/** - * Background thread started by the kernel, which gather statistics and - * monitor/control other processes. - */ -public class StatisticsThread extends Thread { - private final static CmsLog log = CmsLog.getLog(StatisticsThread.class); - - private RepositoryStatisticsImpl repoStats; - - /** The smallest period of operation, in ms */ - private final long PERIOD = 60 * 1000l; - /** One ms in ns */ - private final static long m = 1000l * 1000l; - private final static long M = 1024l * 1024l; - - private boolean running = true; - - private CmsLog kernelStatsLog = CmsLog.getLog("argeo.stats.kernel"); - private CmsLog nodeStatsLog = CmsLog.getLog("argeo.stats.node"); - - @SuppressWarnings("unused") - private long cycle = 0l; - - public StatisticsThread(String name) { - super(name); - } - - private void doSmallestPeriod() { - // Clean expired sessions - // FIXME re-enable it in CMS - //CmsSessionImpl.closeInvalidSessions(); - - if (kernelStatsLog.isDebugEnabled()) { - StringBuilder line = new StringBuilder(64); - line.append("§\t"); - long freeMem = Runtime.getRuntime().freeMemory() / M; - long totalMem = Runtime.getRuntime().totalMemory() / M; - long maxMem = Runtime.getRuntime().maxMemory() / M; - double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); - // in min - boolean min = true; - long uptime = ManagementFactory.getRuntimeMXBean().getUptime() / (1000 * 60); - if (uptime > 24 * 60) { - min = false; - uptime = uptime / 60; - } - line.append(uptime).append(min ? " min" : " h").append('\t'); - line.append(loadAvg).append('\t').append(maxMem).append('\t').append(totalMem).append('\t').append(freeMem) - .append('\t'); - kernelStatsLog.debug(line); - } - - if (nodeStatsLog.isDebugEnabled()) { - File dataDir = KernelUtils.getOsgiInstanceDir(); - long freeSpace = dataDir.getUsableSpace() / M; - // File currentRoot = null; - // for (File root : File.listRoots()) { - // String rootPath = root.getAbsolutePath(); - // if (dataDir.getAbsolutePath().startsWith(rootPath)) { - // if (currentRoot == null - // || (rootPath.length() > currentRoot.getPath() - // .length())) { - // currentRoot = root; - // } - // } - // } - // long totalSpace = currentRoot.getTotalSpace(); - StringBuilder line = new StringBuilder(128); - line.append("§\t").append(freeSpace).append(" MB left in " + dataDir); - line.append('\n'); - if (repoStats != null) - for (RepositoryStatistics.Type type : RepositoryStatistics.Type.values()) { - long[] vals = repoStats.getTimeSeries(type).getValuePerMinute(); - long val = vals[vals.length - 1]; - line.append(type.name()).append('\t').append(val).append('\n'); - } - nodeStatsLog.debug(line); - } - } - - @Override - public void run() { - if (log.isTraceEnabled()) - log.trace("Kernel thread started."); - final long periodNs = PERIOD * m; - while (running) { - long beginNs = System.nanoTime(); - doSmallestPeriod(); - - long waitNs = periodNs - (System.nanoTime() - beginNs); - if (waitNs < 0) - continue; - // wait - try { - sleep(waitNs / m, (int) (waitNs % m)); - } catch (InterruptedException e) { - // silent - } - cycle++; - } - } - - public synchronized void destroyAndJoin() { - running = false; - notifyAll(); -// interrupt(); -// try { -// join(PERIOD * 2); -// } catch (InterruptedException e) { -// // throw new CmsException("Kernel thread destruction was interrupted"); -// log.error("Kernel thread destruction was interrupted", e); -// } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/osgi/CmsJcrActivator.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/osgi/CmsJcrActivator.java deleted file mode 100644 index 57860d84f..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/osgi/CmsJcrActivator.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.argeo.cms.jcr.internal.osgi; - -import java.util.Dictionary; - -import org.argeo.cms.jcr.internal.StatisticsThread; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class CmsJcrActivator implements BundleActivator { - private static BundleContext bundleContext; - -// private List stopHooks = new ArrayList<>(); - private StatisticsThread kernelThread; - -// private JackrabbitRepositoryContextsFactory repositoryServiceFactory; -// private CmsJcrDeployment jcrDeployment; - - @Override - public void start(BundleContext context) throws Exception { - bundleContext = context; - - // kernel thread - kernelThread = new StatisticsThread("Kernel Thread"); - kernelThread.setContextClassLoader(getClass().getClassLoader()); - kernelThread.start(); - - // JCR -// repositoryServiceFactory = new JackrabbitRepositoryContextsFactory(); -//// stopHooks.add(() -> repositoryServiceFactory.shutdown()); -// registerService(ManagedServiceFactory.class, repositoryServiceFactory, -// LangUtils.dict(Constants.SERVICE_PID, CmsConstants.NODE_REPOS_FACTORY_PID)); - -// JcrRepositoryFactory repositoryFactory = new JcrRepositoryFactory(); -// registerService(RepositoryFactory.class, repositoryFactory, null); - - // File System -// CmsJcrFsProvider cmsFsProvider = new CmsJcrFsProvider(); -// ServiceLoader fspSl = ServiceLoader.load(FileSystemProvider.class); -// for (FileSystemProvider fsp : fspSl) { -// log.debug("FileSystemProvider " + fsp); -// if (fsp instanceof CmsFsProvider) { -// cmsFsProvider = (CmsFsProvider) fsp; -// } -// } -// for (FileSystemProvider fsp : FileSystemProvider.installedProviders()) { -// log.debug("Installed FileSystemProvider " + fsp); -// } -// registerService(FileSystemProvider.class, cmsFsProvider, -// LangUtils.dict(Constants.SERVICE_PID, CmsConstants.NODE_FS_PROVIDER_PID)); - -// jcrDeployment = new CmsJcrDeployment(); -// jcrDeployment.init(); - } - - @Override - public void stop(BundleContext context) throws Exception { -// if (jcrDeployment != null) -// jcrDeployment.destroy(); - -// if (repositoryServiceFactory != null) -// repositoryServiceFactory.shutdown(); - - if (kernelThread != null) - kernelThread.destroyAndJoin(); - - bundleContext = null; - } - - @Deprecated - public static void registerService(Class clss, T service, Dictionary properties) { - if (bundleContext != null) { - bundleContext.registerService(clss, service, properties); - } - - } - - @Deprecated - public static BundleContext getBundleContext() { - return bundleContext; - } - - @Deprecated - public static T getService(Class clss) { - if (bundleContext != null) { - return bundleContext.getService(bundleContext.getServiceReference(clss)); - } else { - return null; - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsRemotingServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsRemotingServlet.java deleted file mode 100644 index fa3f87f67..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsRemotingServlet.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.util.Map; - -import javax.jcr.Repository; - -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; -import org.argeo.api.cms.CmsConstants; - -/** A {@link JcrRemotingServlet} based on {@link CmsSessionProvider}. */ -public class CmsRemotingServlet extends JcrRemotingServlet { - private static final long serialVersionUID = 6459455509684213633L; - private Repository repository; - private SessionProvider sessionProvider; - - public CmsRemotingServlet() { - } - - public CmsRemotingServlet(String alias, Repository repository) { - this.repository = repository; - this.sessionProvider = new CmsSessionProvider(alias); - } - - @Override - public Repository getRepository() { - return repository; - } - - public void setRepository(Repository repository, Map properties) { - this.repository = repository; - String alias = properties.get(CmsConstants.CN); - if (alias != null) - sessionProvider = new CmsSessionProvider(alias); - else - throw new IllegalArgumentException("Only aliased repositories are supported"); - } - - @Override - protected SessionProvider getSessionProvider() { - return sessionProvider; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsSessionProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsSessionProvider.java deleted file mode 100644 index 4e067eea2..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsSessionProvider.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.io.Serializable; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - -import org.apache.jackrabbit.server.SessionProvider; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsSession; -import org.argeo.cms.auth.RemoteAuthUtils; -import org.argeo.cms.servlet.ServletHttpRequest; -import org.argeo.jcr.JcrUtils; - -/** - * Implements an open session in view patter: a new JCR session is created for - * each request - */ -public class CmsSessionProvider implements SessionProvider, Serializable { - private static final long serialVersionUID = -1358136599534938466L; - - private final static CmsLog log = CmsLog.getLog(CmsSessionProvider.class); - - private final String alias; - - private LinkedHashMap cmsSessions = new LinkedHashMap<>(); - - public CmsSessionProvider(String alias) { - this.alias = alias; - } - - public Session getSession(HttpServletRequest request, Repository rep, String workspace) - throws javax.jcr.LoginException, ServletException, RepositoryException { - - // a client is scanning parent URLs. -// if (workspace == null) -// return null; - - CmsSession cmsSession = RemoteAuthUtils.getCmsSession(new ServletHttpRequest(request)); - // CmsSessionImpl cmsSession = WebCmsSessionImpl.getCmsSession(request); - if (log.isTraceEnabled()) { - log.trace("Get JCR session from " + cmsSession); - } - if (cmsSession == null) - throw new IllegalStateException("Cannot find a session for request " + request.getRequestURI()); - CmsDataSession cmsDataSession = new CmsDataSession(cmsSession); - Session session = cmsDataSession.getDataSession(alias, workspace, rep); - cmsSessions.put(session, cmsDataSession); - return session; - } - - public void releaseSession(Session session) { -// JcrUtils.logoutQuietly(session); - if (cmsSessions.containsKey(session)) { - CmsDataSession cmsDataSession = cmsSessions.get(session); - cmsDataSession.releaseDataSession(alias, session); - } else { - log.warn("JCR session " + session + " not found in CMS session list. Logging it out..."); - JcrUtils.logoutQuietly(session); - } - } - - static class CmsDataSession { - private CmsSession cmsSession; - - private Map dataSessions = new HashMap<>(); - private Set dataSessionsInUse = new HashSet<>(); - private Set additionalDataSessions = new HashSet<>(); - - private CmsDataSession(CmsSession cmsSession) { - this.cmsSession = cmsSession; - cmsSession.addOnCloseCallback((sess) -> close()); - } - - public Session newDataSession(String cn, String workspace, Repository repository) { - checkValid(); - return login(repository, workspace); - } - - public synchronized Session getDataSession(String cn, String workspace, Repository repository) { - checkValid(); - // FIXME make it more robust - if (workspace == null) - workspace = CmsConstants.SYS_WORKSPACE; - String path = cn + '/' + workspace; - if (dataSessionsInUse.contains(path)) { - try { - wait(1000); - if (dataSessionsInUse.contains(path)) { - Session session = login(repository, workspace); - additionalDataSessions.add(session); - if (log.isTraceEnabled()) - log.trace("Additional data session " + path + " for " + cmsSession.getUserDn()); - return session; - } - } catch (InterruptedException e) { - // silent - } - } - - Session session = null; - if (dataSessions.containsKey(path)) { - session = dataSessions.get(path); - } else { - session = login(repository, workspace); - dataSessions.put(path, session); - if (log.isTraceEnabled()) - log.trace("New data session " + path + " for " + cmsSession.getUserDn()); - } - dataSessionsInUse.add(path); - return session; - } - - private Session login(Repository repository, String workspace) { - try { - return Subject.doAs(cmsSession.getSubject(), new PrivilegedExceptionAction() { - @Override - public Session run() throws Exception { - return repository.login(workspace); - } - }); - } catch (PrivilegedActionException e) { - throw new IllegalStateException("Cannot log in " + cmsSession.getUserDn() + " to JCR", e); - } - } - - public synchronized void releaseDataSession(String cn, Session session) { - if (additionalDataSessions.contains(session)) { - JcrUtils.logoutQuietly(session); - additionalDataSessions.remove(session); - if (log.isTraceEnabled()) - log.trace("Remove additional data session " + session); - return; - } - String path = cn + '/' + session.getWorkspace().getName(); - if (!dataSessionsInUse.contains(path)) - log.warn("Data session " + path + " was not in use for " + cmsSession.getUserDn()); - dataSessionsInUse.remove(path); - Session registeredSession = dataSessions.get(path); - if (session != registeredSession) - log.warn("Data session " + path + " not consistent for " + cmsSession.getUserDn()); - if (log.isTraceEnabled()) - log.trace("Released data session " + session + " for " + path); - notifyAll(); - } - - private void checkValid() { - if (!cmsSession.isValid()) - throw new IllegalStateException( - "CMS session " + cmsSession.getUuid() + " is not valid since " + cmsSession.getEnd()); - } - - protected void close() { - synchronized (this) { - // TODO check data session in use ? - for (String path : dataSessions.keySet()) - JcrUtils.logoutQuietly(dataSessions.get(path)); - for (Session session : additionalDataSessions) - JcrUtils.logoutQuietly(session); - } - } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsWebDavServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsWebDavServlet.java deleted file mode 100644 index 0f0858f51..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsWebDavServlet.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.util.Map; - -import javax.jcr.Repository; - -import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; -import org.argeo.api.cms.CmsConstants; - -/** A {@link SimpleWebdavServlet} based on {@link CmsSessionProvider}. */ -public class CmsWebDavServlet extends SimpleWebdavServlet { - private static final long serialVersionUID = 7485800288686328063L; - private Repository repository; - - public CmsWebDavServlet() { - } - - public CmsWebDavServlet(String alias, Repository repository) { - this.repository = repository; - setSessionProvider(new CmsSessionProvider(alias)); - } - - @Override - public Repository getRepository() { - return repository; - } - - public void setRepository(Repository repository, Map properties) { - this.repository = repository; - String alias = properties.get(CmsConstants.CN); - if (alias != null) - setSessionProvider(new CmsSessionProvider(alias)); - else - throw new IllegalArgumentException("Only aliased repositories are supported"); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/DataServletContext.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/DataServletContext.java deleted file mode 100644 index 2f60e97d9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/DataServletContext.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import org.argeo.cms.servlet.CmsServletContext; - -/** Internal subclass, so that config resources can be loaded from our bundle. */ -public class DataServletContext extends CmsServletContext { - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrHttpUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrHttpUtils.java deleted file mode 100644 index 11e903db8..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrHttpUtils.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.util.Enumeration; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.api.cms.CmsLog; - -public class JcrHttpUtils { - public final static String HEADER_AUTHORIZATION = "Authorization"; - public final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; - - public final static String DEFAULT_PROTECTED_HANDLERS = "/org/argeo/cms/jcr/internal/servlet/protectedHandlers.xml"; - public final static String WEBDAV_CONFIG = "/org/argeo/cms/jcr/internal/servlet/webdav-config.xml"; - - static boolean isBrowser(String userAgent) { - return userAgent.contains("webkit") || userAgent.contains("gecko") || userAgent.contains("firefox") - || userAgent.contains("msie") || userAgent.contains("chrome") || userAgent.contains("chromium") - || userAgent.contains("opera") || userAgent.contains("browser"); - } - - public static void logResponseHeaders(CmsLog log, HttpServletResponse response) { - if (!log.isDebugEnabled()) - return; - for (String headerName : response.getHeaderNames()) { - Object headerValue = response.getHeader(headerName); - log.debug(headerName + ": " + headerValue); - } - } - - public static void logRequestHeaders(CmsLog log, HttpServletRequest request) { - if (!log.isDebugEnabled()) - return; - for (Enumeration headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) { - String headerName = headerNames.nextElement(); - Object headerValue = request.getHeader(headerName); - log.debug(headerName + ": " + headerValue); - } - log.debug(request.getRequestURI() + "\n"); - } - - public static void logRequest(CmsLog log, HttpServletRequest request) { - log.debug("contextPath=" + request.getContextPath()); - log.debug("servletPath=" + request.getServletPath()); - log.debug("requestURI=" + request.getRequestURI()); - log.debug("queryString=" + request.getQueryString()); - StringBuilder buf = new StringBuilder(); - // headers - Enumeration en = request.getHeaderNames(); - while (en.hasMoreElements()) { - String header = en.nextElement(); - Enumeration values = request.getHeaders(header); - while (values.hasMoreElements()) - buf.append(" " + header + ": " + values.nextElement()); - buf.append('\n'); - } - - // attributed - Enumeration an = request.getAttributeNames(); - while (an.hasMoreElements()) { - String attr = an.nextElement(); - Object value = request.getAttribute(attr); - buf.append(" " + attr + ": " + value); - buf.append('\n'); - } - log.debug("\n" + buf); - } - - private JcrHttpUtils() { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrReadServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrReadServlet.java deleted file mode 100644 index b0cd7897c..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrReadServlet.java +++ /dev/null @@ -1,319 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.security.AccessControlContext; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; -import javax.security.auth.Subject; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.IOUtils; -import org.apache.jackrabbit.api.JackrabbitNode; -import org.apache.jackrabbit.api.JackrabbitValue; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.integration.CmsExceptionsChain; -import org.argeo.jcr.JcrUtils; -import org.osgi.service.http.context.ServletContextHelper; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** Access a JCR repository via web services. */ -public class JcrReadServlet extends HttpServlet { - private static final long serialVersionUID = 6536175260540484539L; - private final static CmsLog log = CmsLog.getLog(JcrReadServlet.class); - - protected final static String ACCEPT_HTTP_HEADER = "Accept"; - protected final static String CONTENT_DISPOSITION_HTTP_HEADER = "Content-Disposition"; - - protected final static String OCTET_STREAM_CONTENT_TYPE = "application/octet-stream"; - protected final static String XML_CONTENT_TYPE = "application/xml"; - protected final static String JSON_CONTENT_TYPE = "application/json"; - - private final static String PARAM_VERBOSE = "verbose"; - private final static String PARAM_DEPTH = "depth"; - - protected final static String JCR_NODES = "jcr:nodes"; - // cf. javax.jcr.Property - protected final static String JCR_PATH = "path"; - protected final static String JCR_NAME = "name"; - - protected final static String _JCR = "_jcr"; - protected final static String JCR_PREFIX = "jcr:"; - protected final static String REP_PREFIX = "rep:"; - - private Repository repository; - private Integer maxDepth = 8; - - private ObjectMapper objectMapper = new ObjectMapper(); - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (log.isTraceEnabled()) - log.trace("Data service: " + req.getPathInfo()); - - String dataWorkspace = getWorkspace(req); - String jcrPath = getJcrPath(req); - - boolean verbose = req.getParameter(PARAM_VERBOSE) != null && !req.getParameter(PARAM_VERBOSE).equals("false"); - int depth = 1; - if (req.getParameter(PARAM_DEPTH) != null) { - depth = Integer.parseInt(req.getParameter(PARAM_DEPTH)); - if (depth > maxDepth) - throw new RuntimeException("Depth " + depth + " is higher than maximum " + maxDepth); - } - - Session session = null; - try { - // authentication - session = openJcrSession(req, resp, getRepository(), dataWorkspace); - if (!session.itemExists(jcrPath)) - throw new RuntimeException("JCR node " + jcrPath + " does not exist"); - Node node = session.getNode(jcrPath); - - List acceptHeader = readAcceptHeader(req); - if (!acceptHeader.isEmpty() && node.isNodeType(NodeType.NT_FILE)) { - resp.setContentType(OCTET_STREAM_CONTENT_TYPE); - resp.addHeader(CONTENT_DISPOSITION_HTTP_HEADER, "attachment; filename='" + node.getName() + "'"); - IOUtils.copy(JcrUtils.getFileAsStream(node), resp.getOutputStream()); - resp.flushBuffer(); - } else { - if (!acceptHeader.isEmpty() && acceptHeader.get(0).equals(XML_CONTENT_TYPE)) { - // TODO Use req.startAsync(); ? - resp.setContentType(XML_CONTENT_TYPE); - session.exportSystemView(node.getPath(), resp.getOutputStream(), false, depth <= 1); - return; - } - if (!acceptHeader.isEmpty() && !acceptHeader.contains(JSON_CONTENT_TYPE)) { - if (log.isTraceEnabled()) - log.warn("Content type " + acceptHeader + " in Accept header is not supported. Supported: " - + JSON_CONTENT_TYPE + " (default), " + XML_CONTENT_TYPE); - } - resp.setContentType(JSON_CONTENT_TYPE); - JsonGenerator jsonGenerator = getObjectMapper().getFactory().createGenerator(resp.getWriter()); - jsonGenerator.writeStartObject(); - writeNodeChildren(node, jsonGenerator, depth, verbose); - writeNodeProperties(node, jsonGenerator, verbose); - jsonGenerator.writeEndObject(); - jsonGenerator.flush(); - } - } catch (Exception e) { - new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - protected Session openJcrSession(HttpServletRequest req, HttpServletResponse resp, Repository repository, - String workspace) throws RepositoryException { - AccessControlContext acc = (AccessControlContext) req.getAttribute(ServletContextHelper.REMOTE_USER); - Subject subject = Subject.getSubject(acc); - try { - return Subject.doAs(subject, new PrivilegedExceptionAction() { - - @Override - public Session run() throws RepositoryException { - return repository.login(workspace); - } - - }); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof RepositoryException) - throw (RepositoryException) e.getException(); - else - throw new RuntimeException(e.getException()); - } -// return workspace != null ? repository.login(workspace) : repository.login(); - } - - protected String getWorkspace(HttpServletRequest req) { - String path = req.getPathInfo(); - try { - path = URLDecoder.decode(path, StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e); - } - String[] pathTokens = path.split("/"); - return pathTokens[1]; - } - - protected String getJcrPath(HttpServletRequest req) { - String path = req.getPathInfo(); - try { - path = URLDecoder.decode(path, StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e); - } - String[] pathTokens = path.split("/"); - String domain = pathTokens[1]; - String jcrPath = path.substring(domain.length() + 1); - return jcrPath; - } - - protected List readAcceptHeader(HttpServletRequest req) { - List lst = new ArrayList<>(); - String acceptHeader = req.getHeader(ACCEPT_HTTP_HEADER); - if (acceptHeader == null) - return lst; -// Enumeration acceptHeader = req.getHeaders(ACCEPT_HTTP_HEADER); -// while (acceptHeader.hasMoreElements()) { - String[] arr = acceptHeader.split("\\."); - for (int i = 0; i < arr.length; i++) { - String str = arr[i].trim(); - if (!"".equals(str)) - lst.add(str); - } -// } - return lst; - } - - protected void writeNodeProperties(Node node, JsonGenerator jsonGenerator, boolean verbose) - throws RepositoryException, IOException { - String jcrPath = node.getPath(); - Map> namespaces = new TreeMap<>(); - - PropertyIterator pit = node.getProperties(); - properties: while (pit.hasNext()) { - Property property = pit.nextProperty(); - - final String propertyName = property.getName(); - int columnIndex = propertyName.indexOf(':'); - if (columnIndex > 0) { - // mark prefix with a '_' before the name of the object, according to JSON - // conventions to indicate a special value - String prefix = "_" + propertyName.substring(0, columnIndex); - String unqualifiedName = propertyName.substring(columnIndex + 1); - if (!namespaces.containsKey(prefix)) - namespaces.put(prefix, new LinkedHashMap()); - Map map = namespaces.get(prefix); - assert !map.containsKey(unqualifiedName); - map.put(unqualifiedName, property); - continue properties; - } - - if (property.getType() == PropertyType.BINARY) { - if (!(node instanceof JackrabbitNode)) { - continue properties;// skip - } - } - - writeProperty(propertyName, property, jsonGenerator); - } - - for (String prefix : namespaces.keySet()) { - Map map = namespaces.get(prefix); - jsonGenerator.writeFieldName(prefix); - jsonGenerator.writeStartObject(); - if (_JCR.equals(prefix)) { - jsonGenerator.writeStringField(JCR_NAME, node.getName()); - jsonGenerator.writeStringField(JCR_PATH, jcrPath); - } - properties: for (String unqualifiedName : map.keySet()) { - Property property = map.get(unqualifiedName); - if (property.getType() == PropertyType.BINARY) { - if (!(node instanceof JackrabbitNode)) { - continue properties;// skip - } - } - writeProperty(unqualifiedName, property, jsonGenerator); - } - jsonGenerator.writeEndObject(); - } - } - - protected void writeProperty(String fieldName, Property property, JsonGenerator jsonGenerator) - throws RepositoryException, IOException { - if (!property.isMultiple()) { - jsonGenerator.writeFieldName(fieldName); - writePropertyValue(property.getType(), property.getValue(), jsonGenerator); - } else { - jsonGenerator.writeFieldName(fieldName); - jsonGenerator.writeStartArray(); - Value[] values = property.getValues(); - for (Value value : values) { - writePropertyValue(property.getType(), value, jsonGenerator); - } - jsonGenerator.writeEndArray(); - } - } - - protected void writePropertyValue(int type, Value value, JsonGenerator jsonGenerator) - throws RepositoryException, IOException { - if (type == PropertyType.DOUBLE) - jsonGenerator.writeNumber(value.getDouble()); - else if (type == PropertyType.LONG) - jsonGenerator.writeNumber(value.getLong()); - else if (type == PropertyType.BINARY) { - if (value instanceof JackrabbitValue) { - String contentIdentity = ((JackrabbitValue) value).getContentIdentity(); - jsonGenerator.writeString("SHA256:" + contentIdentity); - } else { - // TODO write Base64 ? - jsonGenerator.writeNull(); - } - } else - jsonGenerator.writeString(value.getString()); - } - - protected void writeNodeChildren(Node node, JsonGenerator jsonGenerator, int depth, boolean verbose) - throws RepositoryException, IOException { - if (!node.hasNodes()) - return; - if (depth <= 0) - return; - NodeIterator nit; - - nit = node.getNodes(); - children: while (nit.hasNext()) { - Node child = nit.nextNode(); - if (!verbose && child.getName().startsWith(REP_PREFIX)) { - continue children;// skip Jackrabbit auth metadata - } - - jsonGenerator.writeFieldName(child.getName()); - jsonGenerator.writeStartObject(); - writeNodeChildren(child, jsonGenerator, depth - 1, verbose); - writeNodeProperties(child, jsonGenerator, verbose); - jsonGenerator.writeEndObject(); - } - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setMaxDepth(Integer maxDepth) { - this.maxDepth = maxDepth; - } - - protected Repository getRepository() { - return repository; - } - - protected ObjectMapper getObjectMapper() { - return objectMapper; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrServletContext.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrServletContext.java deleted file mode 100644 index 21046f34e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrServletContext.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import org.argeo.cms.servlet.PrivateWwwAuthServletContext; - -/** Internal subclass, so that config resources can be loaded from our bundle. */ -public class JcrServletContext extends PrivateWwwAuthServletContext { - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrWriteServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrWriteServlet.java deleted file mode 100644 index 459a1e493..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/JcrWriteServlet.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import java.io.IOException; - -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.Node; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.integration.CmsExceptionsChain; -import org.argeo.jcr.JcrUtils; - -/** Access a JCR repository via web services. */ -public class JcrWriteServlet extends JcrReadServlet { - private static final long serialVersionUID = 17272653843085492L; - private final static CmsLog log = CmsLog.getLog(JcrWriteServlet.class); - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (log.isDebugEnabled()) - log.debug("Data service POST: " + req.getPathInfo()); - - String dataWorkspace = getWorkspace(req); - String jcrPath = getJcrPath(req); - - Session session = null; - try { - // authentication - session = openJcrSession(req, resp, getRepository(), dataWorkspace); - - if (req.getContentType() != null && req.getContentType().equals(XML_CONTENT_TYPE)) { -// resp.setContentType(XML_CONTENT_TYPE); - session.getWorkspace().importXML(jcrPath, req.getInputStream(), - ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING); - return; - } - - if (!session.itemExists(jcrPath)) { - String parentPath = FilenameUtils.getFullPathNoEndSeparator(jcrPath); - String fileName = FilenameUtils.getName(jcrPath); - Node folderNode = JcrUtils.mkfolders(session, parentPath); - byte[] bytes = IOUtils.toByteArray(req.getInputStream()); - JcrUtils.copyBytesAsFile(folderNode, fileName, bytes); - } else { - Node node = session.getNode(jcrPath); - if (!node.isNodeType(NodeType.NT_FILE)) - throw new IllegalArgumentException("Node " + jcrPath + " exists but is not a file"); - byte[] bytes = IOUtils.toByteArray(req.getInputStream()); - JcrUtils.copyBytesAsFile(node.getParent(), node.getName(), bytes); - } - session.save(); - } catch (Exception e) { - new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - @Override - protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (log.isDebugEnabled()) - log.debug("Data service DELETE: " + req.getPathInfo()); - - String dataWorkspace = getWorkspace(req); - String jcrPath = getJcrPath(req); - - Session session = null; - try { - // authentication - session = openJcrSession(req, resp, getRepository(), dataWorkspace); - if (!session.itemExists(jcrPath)) { - // ignore - return; - } else { - Node node = session.getNode(jcrPath); - node.remove(); - } - session.save(); - } catch (Exception e) { - new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp); - } finally { - JcrUtils.logoutQuietly(session); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java deleted file mode 100644 index be5684acc..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java +++ /dev/null @@ -1,258 +0,0 @@ -package org.argeo.cms.jcr.internal.servlet; - -import static javax.jcr.Property.JCR_DESCRIPTION; -import static javax.jcr.Property.JCR_LAST_MODIFIED; -import static javax.jcr.Property.JCR_TITLE; - -import java.io.IOException; -import java.io.PrintWriter; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.PrivilegedExceptionAction; -import java.util.Calendar; -import java.util.Collection; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.api.cms.CmsAuth; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jcr.JcrUtils; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; - -public class LinkServlet extends HttpServlet { - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - private static final long serialVersionUID = 3749990143146845708L; - - @Override - protected void service(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String path = request.getPathInfo(); - String userAgent = request.getHeader("User-Agent").toLowerCase(); - boolean isBot = false; - // boolean isCompatibleBrowser = false; - if (userAgent.contains("bot") || userAgent.contains("facebook") || userAgent.contains("twitter")) { - isBot = true; - } - // else if (userAgent.contains("webkit") || - // userAgent.contains("gecko") || userAgent.contains("firefox") - // || userAgent.contains("msie") || userAgent.contains("chrome") || - // userAgent.contains("chromium") - // || userAgent.contains("opera") || userAgent.contains("browser")) - // { - // isCompatibleBrowser = true; - // } - - if (isBot) { - // log.warn("# BOT " + request.getHeader("User-Agent")); - canonicalAnswer(request, response, path); - return; - } - - // if (isCompatibleBrowser && log.isTraceEnabled()) - // log.trace("# BWS " + request.getHeader("User-Agent")); - redirectTo(response, "/#" + path); - } - - private void redirectTo(HttpServletResponse response, String location) { - response.setHeader("Location", location); - response.setStatus(HttpServletResponse.SC_FOUND); - } - - // private boolean canonicalAnswerNeededBy(HttpServletRequest request) { - // String userAgent = request.getHeader("User-Agent").toLowerCase(); - // return userAgent.startsWith("facebookexternalhit/"); - // } - - /** For bots which don't understand RWT. */ - private void canonicalAnswer(HttpServletRequest request, HttpServletResponse response, String path) { - Session session = null; - try { - PrintWriter writer = response.getWriter(); - session = Subject.doAs(anonymousLogin(), new PrivilegedExceptionAction() { - - @Override - public Session run() throws Exception { - Collection> srs = bc.getServiceReferences(Repository.class, - "(" + CmsConstants.CN + "=" + CmsConstants.EGO_REPOSITORY + ")"); - Repository repository = bc.getService(srs.iterator().next()); - return repository.login(); - } - - }); - Node node = session.getNode(path); - String title = node.hasProperty(JCR_TITLE) ? node.getProperty(JCR_TITLE).getString() : node.getName(); - String desc = node.hasProperty(JCR_DESCRIPTION) ? node.getProperty(JCR_DESCRIPTION).getString() : null; - Calendar lastUpdate = node.hasProperty(JCR_LAST_MODIFIED) ? node.getProperty(JCR_LAST_MODIFIED).getDate() - : null; - String url = getCanonicalUrl(node, request); - String imgUrl = null; - // TODO support images -// loop: for (NodeIterator it = node.getNodes(); it.hasNext();) { -// // Takes the first found cms:image -// Node child = it.nextNode(); -// if (child.isNodeType(CMS_IMAGE)) { -// imgUrl = getDataUrl(child, request); -// break loop; -// } -// } - StringBuilder buf = new StringBuilder(); - buf.append(""); - buf.append(""); - writeMeta(buf, "og:title", escapeHTML(title)); - writeMeta(buf, "og:type", "website"); - buf.append(""); - buf.append(""); - writeMeta(buf, "og:url", url); - if (desc != null) - writeMeta(buf, "og:description", escapeHTML(desc)); - if (imgUrl != null) - writeMeta(buf, "og:image", imgUrl); - if (lastUpdate != null) - writeMeta(buf, "og:updated_time", Long.toString(lastUpdate.getTime().getTime())); - buf.append(""); - buf.append(""); - buf.append("

!! This page is meant for indexing robots, not for real people," + " visit ").append(escapeHTML(title)).append(" instead.

"); - writeCanonical(buf, node); - buf.append(""); - buf.append(""); - writer.print(buf.toString()); - - response.setHeader("Content-Type", "text/html"); - writer.flush(); - } catch (Exception e) { - throw new IllegalStateException("Cannot write canonical answer", e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - /** - * From http://stackoverflow.com/questions/1265282/recommended-method-for- - * escaping-html-in-java (+ escaping '). TODO Use - * org.apache.commons.lang.StringEscapeUtils - */ - private String escapeHTML(String s) { - StringBuilder out = new StringBuilder(Math.max(16, s.length())); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c > 127 || c == '\'' || c == '"' || c == '<' || c == '>' || c == '&') { - out.append("&#"); - out.append((int) c); - out.append(';'); - } else { - out.append(c); - } - } - return out.toString(); - } - - private void writeMeta(StringBuilder buf, String tag, String value) { - buf.append(""); - } - - private void writeCanonical(StringBuilder buf, Node node) throws RepositoryException { - buf.append("
"); - if (node.hasProperty(JCR_TITLE)) - buf.append("

").append(node.getProperty(JCR_TITLE).getString()).append("

"); - if (node.hasProperty(JCR_DESCRIPTION)) - buf.append("

").append(node.getProperty(JCR_DESCRIPTION).getString()).append("

"); - NodeIterator children = node.getNodes(); - while (children.hasNext()) { - writeCanonical(buf, children.nextNode()); - } - buf.append("
"); - } - - // DATA - private StringBuilder getServerBaseUrl(HttpServletRequest request) { - try { - URL url = new URL(request.getRequestURL().toString()); - StringBuilder buf = new StringBuilder(); - buf.append(url.getProtocol()).append("://").append(url.getHost()); - if (url.getPort() != -1) - buf.append(':').append(url.getPort()); - return buf; - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot extract server base URL from " + request.getRequestURL(), e); - } - } - - private String getDataUrl(Node node, HttpServletRequest request) throws RepositoryException { - try { - StringBuilder buf = getServerBaseUrl(request); - buf.append(CmsJcrUtils.getDataPath(CmsConstants.EGO_REPOSITORY, node)); - return new URL(buf.toString()).toString(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot build data URL for " + node, e); - } - } - - // public static String getDataPath(Node node) throws - // RepositoryException { - // assert node != null; - // String userId = node.getSession().getUserID(); - //// if (log.isTraceEnabled()) - //// log.trace(userId + " : " + node.getPath()); - // StringBuilder buf = new StringBuilder(); - // boolean isAnonymous = - // userId.equalsIgnoreCase(NodeConstants.ROLE_ANONYMOUS); - // if (isAnonymous) - // buf.append(WEBDAV_PUBLIC); - // else - // buf.append(WEBDAV_PRIVATE); - // Session session = node.getSession(); - // Repository repository = session.getRepository(); - // String cn; - // if (repository.isSingleValueDescriptor(NodeConstants.CN)) { - // cn = repository.getDescriptor(NodeConstants.CN); - // } else { - //// log.warn("No cn defined in repository, using " + - // NodeConstants.NODE); - // cn = NodeConstants.NODE; - // } - // return - // buf.append('/').append(cn).append('/').append(session.getWorkspace().getName()).append(node.getPath()) - // .toString(); - // } - - private String getCanonicalUrl(Node node, HttpServletRequest request) throws RepositoryException { - try { - StringBuilder buf = getServerBaseUrl(request); - buf.append('/').append('!').append(node.getPath()); - return new URL(buf.toString()).toString(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot build data URL for " + node, e); - } - // return request.getRequestURL().append('!').append(node.getPath()) - // .toString(); - } - - private Subject anonymousLogin() { - Subject subject = new Subject(); - LoginContext lc; - try { - lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_ANONYMOUS, subject); - lc.login(); - return subject; - } catch (LoginException e) { - throw new IllegalStateException("Cannot login as anonymous", e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/protectedHandlers.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/protectedHandlers.xml deleted file mode 100644 index 59f22cd5e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/protectedHandlers.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/webdav-config.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/webdav-config.xml deleted file mode 100644 index 436389898..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/webdav-config.xml +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nt:file - nt:resource - - - - - - - - - - - - - rep - jcr - - node - argeo - cms - slc - connect - activities - people - documents - tracker - - - - - - - diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/ldap.cnd b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/ldap.cnd deleted file mode 100644 index a2306c60e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/ldap.cnd +++ /dev/null @@ -1 +0,0 @@ - diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/node.cnd b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/node.cnd deleted file mode 100644 index d8a26b64e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/node.cnd +++ /dev/null @@ -1,9 +0,0 @@ - - -[node:userHome] -mixin -- ldap:uid (STRING) m - -[node:groupHome] -mixin -- ldap:cn (STRING) m diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/CsvTabularWriter.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/CsvTabularWriter.java deleted file mode 100644 index ccd543f4d..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/CsvTabularWriter.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.argeo.cms.jcr.tabular; - -import java.io.OutputStream; - -import org.argeo.cms.tabular.TabularWriter; -import org.argeo.util.CsvWriter; - -/** Write tabular content in a stream as CSV. Wraps a {@link CsvWriter}. */ -public class CsvTabularWriter implements TabularWriter { - private CsvWriter csvWriter; - - public CsvTabularWriter(OutputStream out) { - this.csvWriter = new CsvWriter(out); - } - - public void appendRow(Object[] row) { - csvWriter.writeLine(row); - } - - public void close() { - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularRowIterator.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularRowIterator.java deleted file mode 100644 index d1d9b583b..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularRowIterator.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.argeo.cms.jcr.tabular; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.cms.ArgeoTypes; -import org.argeo.cms.tabular.ArrayTabularRow; -import org.argeo.cms.tabular.TabularColumn; -import org.argeo.cms.tabular.TabularRow; -import org.argeo.cms.tabular.TabularRowIterator; -import org.argeo.jcr.JcrException; -import org.argeo.util.CsvParser; - -/** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */ -public class JcrTabularRowIterator implements TabularRowIterator { - private Boolean hasNext = null; - private Boolean parsingCompleted = false; - - private Long currentRowNumber = 0l; - - private List header = new ArrayList(); - - /** referenced so that we can close it */ - private Binary binary; - private InputStream in; - - private CsvParser csvParser; - private ArrayBlockingQueue> textLines; - - public JcrTabularRowIterator(Node tableNode) { - try { - for (NodeIterator it = tableNode.getNodes(); it.hasNext();) { - Node node = it.nextNode(); - if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) { - Integer type = PropertyType.valueFromName(node.getProperty( - Property.JCR_REQUIRED_TYPE).getString()); - TabularColumn tc = new TabularColumn(node.getProperty( - Property.JCR_TITLE).getString(), type); - header.add(tc); - } - } - Node contentNode = tableNode.getNode(Property.JCR_CONTENT); - if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) { - textLines = new ArrayBlockingQueue>(1000); - csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, - List header, List tokens) { - try { - textLines.put(tokens); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // textLines.add(tokens); - if (hasNext == null) { - hasNext = true; - synchronized (JcrTabularRowIterator.this) { - JcrTabularRowIterator.this.notifyAll(); - } - } - } - }; - csvParser.setNoHeader(true); - binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); - in = binary.getStream(); - Thread thread = new Thread(contentNode.getPath() + " reader") { - public void run() { - try { - csvParser.parse(in); - } finally { - parsingCompleted = true; - IOUtils.closeQuietly(in); - } - } - }; - thread.start(); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot read table " + tableNode, e); - } - } - - public synchronized boolean hasNext() { - // we don't know if there is anything available - // while (hasNext == null) - // try { - // wait(); - // } catch (InterruptedException e) { - // // silent - // // FIXME better deal with interruption - // Thread.currentThread().interrupt(); - // break; - // } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // maybe the parsing is finished but the flag has not been set - while (!parsingCompleted && textLines.isEmpty()) - try { - wait(100); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - Thread.currentThread().interrupt(); - break; - } - - // buffer not empty - if (!textLines.isEmpty()) - return true; - - // (parsingCompleted && textLines.isEmpty()) - return false; - - // if (!hasNext && textLines.isEmpty()) { - // if (in != null) { - // IOUtils.closeQuietly(in); - // in = null; - // } - // if (binary != null) { - // JcrUtils.closeQuietly(binary); - // binary = null; - // } - // return false; - // } else - // return true; - } - - public synchronized TabularRow next() { - try { - List tokens = textLines.take(); - List objs = new ArrayList(tokens.size()); - for (String token : tokens) { - // TODO convert to other formats using header - objs.add(token); - } - currentRowNumber++; - return new ArrayTabularRow(objs); - } catch (InterruptedException e) { - // silent - // FIXME better deal with interruption - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public Long getCurrentRowNumber() { - return currentRowNumber; - } - - public List getHeader() { - return header; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularWriter.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularWriter.java deleted file mode 100644 index cc3e0d7a9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/JcrTabularWriter.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.argeo.cms.jcr.tabular; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.List; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.apache.commons.io.IOUtils; -import org.argeo.cms.ArgeoTypes; -import org.argeo.cms.tabular.TabularColumn; -import org.argeo.cms.tabular.TabularWriter; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.CsvWriter; - -/** Write / reference tabular content in a JCR repository. */ -public class JcrTabularWriter implements TabularWriter { - private Node contentNode; - private ByteArrayOutputStream out; - private CsvWriter csvWriter; - - @SuppressWarnings("unused") - private final List columns; - - /** Creates a table node */ - public JcrTabularWriter(Node tableNode, List columns, - String contentNodeType) { - try { - this.columns = columns; - for (TabularColumn column : columns) { - String normalized = JcrUtils.replaceInvalidChars(column - .getName()); - Node columnNode = tableNode.addNode(normalized, - ArgeoTypes.ARGEO_COLUMN); - columnNode.setProperty(Property.JCR_TITLE, column.getName()); - if (column.getType() != null) - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.nameFromValue(column.getType())); - else - columnNode.setProperty(Property.JCR_REQUIRED_TYPE, - PropertyType.TYPENAME_STRING); - } - contentNode = tableNode.addNode(Property.JCR_CONTENT, - contentNodeType); - if (contentNodeType.equals(ArgeoTypes.ARGEO_CSV)) { - contentNode.setProperty(Property.JCR_MIMETYPE, "text/csv"); - contentNode.setProperty(Property.JCR_ENCODING, "UTF-8"); - out = new ByteArrayOutputStream(); - csvWriter = new CsvWriter(out); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot create table node " + tableNode, e); - } - } - - public void appendRow(Object[] row) { - csvWriter.writeLine(row); - } - - public void close() { - Binary binary = null; - InputStream in = null; - try { - // TODO parallelize with pipes and writing from another thread - in = new ByteArrayInputStream(out.toByteArray()); - binary = contentNode.getSession().getValueFactory() - .createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - } catch (RepositoryException e) { - throw new JcrException("Cannot store data in " + contentNode, e); - } finally { - IOUtils.closeQuietly(in); - JcrUtils.closeQuietly(binary); - } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/package-info.java deleted file mode 100644 index 506a6ac98..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/tabular/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo CMS implementation of the Argeo Tabular API (CSV, JCR). */ -package org.argeo.cms.jcr.tabular; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitAdminLoginModule.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitAdminLoginModule.java deleted file mode 100644 index 7396c87e7..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitAdminLoginModule.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.argeo.jackrabbit; - -import java.util.Map; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; - -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; - -@Deprecated -public class JackrabbitAdminLoginModule implements LoginModule { - private Subject subject; - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - this.subject = subject; - } - - @Override - public boolean login() throws LoginException { - // TODO check permission? - return true; - } - - @Override - public boolean commit() throws LoginException { - subject.getPrincipals().add( - new AdminPrincipal(SecurityConstants.ADMIN_ID)); - return true; - } - - @Override - public boolean abort() throws LoginException { - return true; - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals().removeAll( - subject.getPrincipals(AdminPrincipal.class)); - return true; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java deleted file mode 100644 index 8c267e314..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.argeo.jackrabbit; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.apache.jackrabbit.commons.cnd.ParseException; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.core.fs.FileSystemException; -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.JcrCallback; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** Migrate the data in a Jackrabbit repository. */ -@Deprecated -public class JackrabbitDataModelMigration implements Comparable { - private final static CmsLog log = CmsLog.getLog(JackrabbitDataModelMigration.class); - - private String dataModelNodePath; - private String targetVersion; - private URL migrationCnd; - private JcrCallback dataModification; - - /** - * Expects an already started repository with the old data model to migrate. - * Expects to be run with admin rights (Repository.login() will be used). - * - * @return true if a migration was performed and the repository needs to be - * restarted and its caches cleared. - */ - public Boolean migrate(Session session) { - long begin = System.currentTimeMillis(); - Reader reader = null; - try { - // check if already migrated - if (!session.itemExists(dataModelNodePath)) { -// log.warn("Node " + dataModelNodePath + " does not exist: nothing to migrate."); - return false; - } -// Node dataModelNode = session.getNode(dataModelNodePath); -// if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) { -// String currentVersion = dataModelNode.getProperty( -// ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString(); -// if (compareVersions(currentVersion, targetVersion) >= 0) { -// log.info("Data model at version " + currentVersion -// + ", no need to migrate."); -// return false; -// } -// } - - // apply transitional CND - if (migrationCnd != null) { - reader = new InputStreamReader(migrationCnd.openStream()); - CndImporter.registerNodeTypes(reader, session, true); - session.save(); -// log.info("Registered migration node types from " + migrationCnd); - } - - // modify data - dataModification.execute(session); - - // apply changes - session.save(); - - long duration = System.currentTimeMillis() - begin; -// log.info("Migration of data model " + dataModelNodePath + " to " + targetVersion + " performed in " -// + duration + "ms"); - return true; - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new JcrException("Migration of data model " + dataModelNodePath + " to " + targetVersion + " failed.", - e); - } catch (ParseException | IOException e) { - JcrUtils.discardQuietly(session); - throw new RuntimeException( - "Migration of data model " + dataModelNodePath + " to " + targetVersion + " failed.", e); - } finally { - JcrUtils.logoutQuietly(session); - IOUtils.closeQuietly(reader); - } - } - - protected static int compareVersions(String version1, String version2) { - // TODO do a proper version analysis and comparison - return version1.compareTo(version2); - } - - /** To be called on a stopped repository. */ - public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) { - try { - String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml"; - // FIXME causes weird error in Eclipse - repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath); - if (log.isDebugEnabled()) - log.debug("Cleared " + customeNodeTypesPath); - } catch (RuntimeException e) { - throw e; - } catch (RepositoryException e) { - throw new JcrException(e); - } catch (FileSystemException e) { - throw new RuntimeException("Cannot clear node types cache.",e); - } - - // File customNodeTypes = new File(home.getPath() - // + "/repository/nodetypes/custom_nodetypes.xml"); - // if (customNodeTypes.exists()) { - // customNodeTypes.delete(); - // if (log.isDebugEnabled()) - // log.debug("Cleared " + customNodeTypes); - // } else { - // log.warn("File " + customNodeTypes + " not found."); - // } - } - - /* - * FOR USE IN (SORTED) SETS - */ - - public int compareTo(JackrabbitDataModelMigration dataModelMigration) { - // TODO make ordering smarter - if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath)) - return compareVersions(targetVersion, dataModelMigration.targetVersion); - else - return dataModelNodePath.compareTo(dataModelMigration.dataModelNodePath); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof JackrabbitDataModelMigration)) - return false; - JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj; - return dataModelNodePath.equals(dataModelMigration.dataModelNodePath) - && targetVersion.equals(dataModelMigration.targetVersion); - } - - @Override - public int hashCode() { - return targetVersion.hashCode(); - } - - public void setDataModelNodePath(String dataModelNodePath) { - this.dataModelNodePath = dataModelNodePath; - } - - public void setTargetVersion(String targetVersion) { - this.targetVersion = targetVersion; - } - - public void setMigrationCnd(URL migrationCnd) { - this.migrationCnd = migrationCnd; - } - - public void setDataModification(JcrCallback dataModification) { - this.dataModification = dataModification; - } - - public String getDataModelNodePath() { - return dataModelNodePath; - } - - public String getTargetVersion() { - return targetVersion; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryFactory.java deleted file mode 100644 index 77ad527e1..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.argeo.jackrabbit.client; - -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.apache.jackrabbit.jcr2spi.Jcr2spiRepositoryFactory; -import org.apache.jackrabbit.jcr2spi.RepositoryImpl; -import org.apache.jackrabbit.spi.RepositoryServiceFactory; - -/** A customised {@link RepositoryFactory} access a remote DAVEX service. */ -public class ClientDavexRepositoryFactory implements RepositoryFactory { - public final static String JACKRABBIT_DAVEX_URI = ClientDavexRepositoryServiceFactory.PARAM_REPOSITORY_URI; - public final static String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = ClientDavexRepositoryServiceFactory.PARAM_WORKSPACE_NAME_DEFAULT; - - @SuppressWarnings("rawtypes") - @Override - public Repository getRepository(Map parameters) throws RepositoryException { - RepositoryServiceFactory repositoryServiceFactory = new ClientDavexRepositoryServiceFactory(); - return RepositoryImpl - .create(new Jcr2spiRepositoryFactory.RepositoryConfigImpl(repositoryServiceFactory, parameters)); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryService.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryService.java deleted file mode 100644 index 7d86af217..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryService.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.argeo.jackrabbit.client; - -import javax.jcr.RepositoryException; - -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.protocol.HttpContext; -import org.apache.jackrabbit.spi.SessionInfo; -import org.apache.jackrabbit.spi2davex.BatchReadConfig; -import org.apache.jackrabbit.spi2davex.RepositoryServiceImpl; - -/** - * Wrapper for {@link RepositoryServiceImpl} in order to access the underlying - * {@link HttpClientContext}. - */ -public class ClientDavexRepositoryService extends RepositoryServiceImpl { - - public ClientDavexRepositoryService(String jcrServerURI, BatchReadConfig batchReadConfig) - throws RepositoryException { - super(jcrServerURI, batchReadConfig); - } - - - -// public ClientDavexRepositoryService(String jcrServerURI, String defaultWorkspaceName, -// BatchReadConfig batchReadConfig, int itemInfoCacheSize, ConnectionOptions connectionOptions) -// throws RepositoryException { -// super(jcrServerURI, defaultWorkspaceName, batchReadConfig, itemInfoCacheSize, connectionOptions); -// // TODO Auto-generated constructor stub -// } - - - -// public ClientDavexRepositoryService(String jcrServerURI, String defaultWorkspaceName, -// BatchReadConfig batchReadConfig, int itemInfoCacheSize, int maximumHttpConnections) -// throws RepositoryException { -// super(jcrServerURI, defaultWorkspaceName, batchReadConfig, itemInfoCacheSize, maximumHttpConnections); -// } -// -// public ClientDavexRepositoryService(String jcrServerURI, String defaultWorkspaceName, -// BatchReadConfig batchReadConfig, int itemInfoCacheSize) throws RepositoryException { -// super(jcrServerURI, defaultWorkspaceName, batchReadConfig, itemInfoCacheSize); -// } - - @Override - protected HttpContext getContext(SessionInfo sessionInfo) throws RepositoryException { - HttpClientContext result = HttpClientContext.create(); - result.setAuthCache(new NonSerialBasicAuthCache()); - return result; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryServiceFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryServiceFactory.java deleted file mode 100644 index 2af0835ea..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/ClientDavexRepositoryServiceFactory.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.argeo.jackrabbit.client; - -import java.util.Map; - -import javax.jcr.RepositoryException; - -import org.apache.jackrabbit.spi.RepositoryService; -import org.apache.jackrabbit.spi.commons.ItemInfoCacheImpl; -import org.apache.jackrabbit.spi2davex.BatchReadConfig; -import org.apache.jackrabbit.spi2davex.Spi2davexRepositoryServiceFactory; - -/** - * Wrapper for {@link Spi2davexRepositoryServiceFactory} in order to create a - * {@link ClientDavexRepositoryService}. - */ -public class ClientDavexRepositoryServiceFactory extends Spi2davexRepositoryServiceFactory { - @Override - public RepositoryService createRepositoryService(Map parameters) throws RepositoryException { - // retrieve the repository uri - String uri; - if (parameters == null) { - uri = System.getProperty(PARAM_REPOSITORY_URI); - } else { - Object repoUri = parameters.get(PARAM_REPOSITORY_URI); - uri = (repoUri == null) ? null : repoUri.toString(); - } - if (uri == null) { - uri = DEFAULT_REPOSITORY_URI; - } - - // load other optional configuration parameters - BatchReadConfig brc = null; - int itemInfoCacheSize = ItemInfoCacheImpl.DEFAULT_CACHE_SIZE; - int maximumHttpConnections = 0; - - // since JCR-4120 the default workspace name is no longer set to 'default' - // note: if running with JCR Server < 1.5 a default workspace name must - // therefore be configured - String workspaceNameDefault = null; - - if (parameters != null) { - // batchRead config - Object param = parameters.get(PARAM_BATCHREAD_CONFIG); - if (param != null && param instanceof BatchReadConfig) { - brc = (BatchReadConfig) param; - } - - // itemCache size config - param = parameters.get(PARAM_ITEMINFO_CACHE_SIZE); - if (param != null) { - try { - itemInfoCacheSize = Integer.parseInt(param.toString()); - } catch (NumberFormatException e) { - // ignore, use default - } - } - - // max connections config - param = parameters.get(PARAM_MAX_CONNECTIONS); - if (param != null) { - try { - maximumHttpConnections = Integer.parseInt(param.toString()); - } catch (NumberFormatException e) { - // using default - } - } - - param = parameters.get(PARAM_WORKSPACE_NAME_DEFAULT); - if (param != null) { - workspaceNameDefault = param.toString(); - } - } - - // FIXME adapt to changes in Jackrabbit -// if (maximumHttpConnections > 0) { -// return new ClientDavexRepositoryService(uri, workspaceNameDefault, brc, itemInfoCacheSize, -// maximumHttpConnections); -// } else { -// return new ClientDavexRepositoryService(uri, workspaceNameDefault, brc, itemInfoCacheSize); -// } - return null; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/JackrabbitClient.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/JackrabbitClient.java deleted file mode 100644 index 3a122f142..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/JackrabbitClient.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.argeo.jackrabbit.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.protocol.HttpContext; -import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory; -import org.apache.jackrabbit.jcr2spi.Jcr2spiRepositoryFactory; -import org.apache.jackrabbit.jcr2spi.RepositoryImpl; -import org.apache.jackrabbit.spi.RepositoryService; -import org.apache.jackrabbit.spi.RepositoryServiceFactory; -import org.apache.jackrabbit.spi.SessionInfo; -import org.apache.jackrabbit.spi.commons.ItemInfoCacheImpl; -import org.apache.jackrabbit.spi2davex.BatchReadConfig; -import org.apache.jackrabbit.spi2davex.RepositoryServiceImpl; -import org.apache.jackrabbit.spi2davex.Spi2davexRepositoryServiceFactory; -import org.argeo.jcr.JcrUtils; - -/** Minimal client to test JCR DAVEX connectivity. */ -public class JackrabbitClient { - final static String JACKRABBIT_REPOSITORY_URI = "org.apache.jackrabbit.repository.uri"; - final static String JACKRABBIT_DAVEX_URI = "org.apache.jackrabbit.spi2davex.uri"; - final static String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "org.apache.jackrabbit.spi2davex.WorkspaceNameDefault"; - - public static void main(String[] args) { - String repoUri = args.length == 0 ? "http://root:demo@localhost:7070/jcr/ego" : args[0]; - String workspace = args.length < 2 ? "home" : args[1]; - - Repository repository = null; - Session session = null; - - URI uri; - try { - uri = new URI(repoUri); - } catch (URISyntaxException e1) { - throw new IllegalArgumentException(e1); - } - - if (uri.getScheme().equals("http") || uri.getScheme().equals("https")) { - - RepositoryFactory repositoryFactory = new Jcr2davRepositoryFactory() { - @SuppressWarnings("rawtypes") - public Repository getRepository(Map parameters) throws RepositoryException { - RepositoryServiceFactory repositoryServiceFactory = new Spi2davexRepositoryServiceFactory() { - - @Override - public RepositoryService createRepositoryService(Map parameters) - throws RepositoryException { - Object uri = parameters.get(JACKRABBIT_DAVEX_URI); - Object defaultWorkspace = parameters.get(JACKRABBIT_REMOTE_DEFAULT_WORKSPACE); - BatchReadConfig brc = null; - // FIXME adapt to change in Jackrabbit -// return new RepositoryServiceImpl(uri.toString(), defaultWorkspace.toString(), brc, -// ItemInfoCacheImpl.DEFAULT_CACHE_SIZE) { -// -// @Override -// protected HttpContext getContext(SessionInfo sessionInfo) throws RepositoryException { -// HttpClientContext result = HttpClientContext.create(); -// result.setAuthCache(new NonSerialBasicAuthCache()); -// return result; -// } -// -// }; - return null; - } - }; - return RepositoryImpl.create( - new Jcr2spiRepositoryFactory.RepositoryConfigImpl(repositoryServiceFactory, parameters)); - } - }; - Map params = new HashMap(); - params.put(JACKRABBIT_DAVEX_URI, repoUri.toString()); - // FIXME make it configurable - params.put(JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, "sys"); - - try { - repository = repositoryFactory.getRepository(params); - if (repository != null) - session = repository.login(workspace); - else - throw new IllegalArgumentException("Repository " + repoUri + " not found"); - } catch (RepositoryException e) { - e.printStackTrace(); - } - - } else { - Path path = Paths.get(uri.getPath()); - } - - try { - Node rootNode = session.getRootNode(); - NodeIterator nit = rootNode.getNodes(); - while (nit.hasNext()) { - System.out.println(nit.nextNode().getPath()); - } - - Node newNode = JcrUtils.mkdirs(rootNode, "dir/subdir"); - System.out.println("Created folder " + newNode.getPath()); - Node newFile = JcrUtils.copyBytesAsFile(newNode, "test.txt", "TEST".getBytes()); - System.out.println("Created file " + newFile.getPath()); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(JcrUtils.getFileAsStream(newFile)))) { - System.out.println("Read " + reader.readLine()); - } catch (IOException e) { - e.printStackTrace(); - } - newNode.getParent().remove(); - System.out.println("Removed new nodes"); - } catch (RepositoryException e) { - e.printStackTrace(); - } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/NonSerialBasicAuthCache.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/NonSerialBasicAuthCache.java deleted file mode 100644 index 3fb0db9a0..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/client/NonSerialBasicAuthCache.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.jackrabbit.client; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScheme; -import org.apache.http.client.AuthCache; - -/** - * Implementation of {@link AuthCache} which doesn't use serialization, as it is - * not supported by GraalVM at this stage. - */ -public class NonSerialBasicAuthCache implements AuthCache { - private final Map cache; - - public NonSerialBasicAuthCache() { - cache = new ConcurrentHashMap(); - } - - @Override - public void put(HttpHost host, AuthScheme authScheme) { - cache.put(host, authScheme); - } - - @Override - public AuthScheme get(HttpHost host) { - return cache.get(host); - } - - @Override - public void remove(HttpHost host) { - cache.remove(host); - } - - @Override - public void clear() { - cache.clear(); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/AbstractJackrabbitFsProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/AbstractJackrabbitFsProvider.java deleted file mode 100644 index a2eb98302..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/AbstractJackrabbitFsProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.argeo.jackrabbit.fs; - -import org.argeo.jcr.fs.JcrFileSystemProvider; - -public abstract class AbstractJackrabbitFsProvider extends JcrFileSystemProvider { - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/DavexFsProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/DavexFsProvider.java deleted file mode 100644 index 1cae6e493..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/DavexFsProvider.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.argeo.jackrabbit.fs; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.argeo.jackrabbit.client.ClientDavexRepositoryFactory; -import org.argeo.jcr.fs.JcrFileSystem; -import org.argeo.jcr.fs.JcrFsException; - -/** - * A file system provider based on a JCR repository remotely accessed via the - * DAVEX protocol. - */ -public class DavexFsProvider extends AbstractJackrabbitFsProvider { - final static String DEFAULT_JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "sys"; - - private Map fileSystems = new HashMap<>(); - - @Override - public String getScheme() { - return "davex"; - } - - @Override - public FileSystem newFileSystem(URI uri, Map env) throws IOException { - if (uri.getHost() == null) - throw new IllegalArgumentException("An host should be provided"); - try { - URI repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null); - String repoKey = repoUri.toString(); - if (fileSystems.containsKey(repoKey)) - throw new FileSystemAlreadyExistsException("CMS file system already exists for " + repoKey); - RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory(); - return tryGetRepo(repositoryFactory, repoUri, "home"); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Cannot open file system " + uri, e); - } - } - - private JcrFileSystem tryGetRepo(RepositoryFactory repositoryFactory, URI repoUri, String workspace) - throws IOException { - Map params = new HashMap(); - params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, repoUri.toString()); - // TODO better integrate with OSGi or other configuration than system - // properties. - String remoteDefaultWorkspace = System.getProperty( - ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, - DEFAULT_JACKRABBIT_REMOTE_DEFAULT_WORKSPACE); - params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, remoteDefaultWorkspace); - Repository repository = null; - Session session = null; - try { - repository = repositoryFactory.getRepository(params); - if (repository != null) - session = repository.login(workspace); - } catch (Exception e) { - // silent - } - - if (session == null) { - if (repoUri.getPath() == null || repoUri.getPath().equals("/")) - return null; - String repoUriStr = repoUri.toString(); - if (repoUriStr.endsWith("/")) - repoUriStr = repoUriStr.substring(0, repoUriStr.length() - 1); - String nextRepoUriStr = repoUriStr.substring(0, repoUriStr.lastIndexOf('/')); - String nextWorkspace = repoUriStr.substring(repoUriStr.lastIndexOf('/') + 1); - URI nextUri; - try { - nextUri = new URI(nextRepoUriStr); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Badly formatted URI", e); - } - return tryGetRepo(repositoryFactory, nextUri, nextWorkspace); - } else { - JcrFileSystem fileSystem = new JcrFileSystem(this, repository); - fileSystems.put(repoUri.toString() + "/" + workspace, fileSystem); - return fileSystem; - } - } - - @Override - public FileSystem getFileSystem(URI uri) { - return currentUserFileSystem(uri); - } - - @Override - public Path getPath(URI uri) { - JcrFileSystem fileSystem = currentUserFileSystem(uri); - if (fileSystem == null) - try { - fileSystem = (JcrFileSystem) newFileSystem(uri, new HashMap()); - if (fileSystem == null) - throw new IllegalArgumentException("No file system found for " + uri); - } catch (IOException e) { - throw new JcrFsException("Could not autocreate file system", e); - } - URI repoUri = null; - try { - repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - String uriStr = repoUri.toString(); - String localPath = null; - for (String key : fileSystems.keySet()) { - if (uriStr.startsWith(key)) { - localPath = uriStr.toString().substring(key.length()); - } - } - if ("".equals(localPath)) - localPath = "/"; - return fileSystem.getPath(localPath); - } - - private JcrFileSystem currentUserFileSystem(URI uri) { - for (String key : fileSystems.keySet()) { - if (uri.toString().startsWith(key)) - return fileSystems.get(key); - } - return null; - } - - public static void main(String args[]) { - try { - DavexFsProvider fsProvider = new DavexFsProvider(); - Path path = fsProvider.getPath(new URI("davex://root:demo@localhost:7070/jcr/ego/")); - System.out.println(path); - DirectoryStream ds = Files.newDirectoryStream(path); - for (Path p : ds) { - System.out.println("- " + p); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/JackrabbitMemoryFsProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/JackrabbitMemoryFsProvider.java deleted file mode 100644 index e3a70d084..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/JackrabbitMemoryFsProvider.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.argeo.jackrabbit.fs; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Credentials; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.argeo.jcr.fs.JcrFileSystem; -import org.argeo.jcr.fs.JcrFsException; - -public class JackrabbitMemoryFsProvider extends AbstractJackrabbitFsProvider { - private RepositoryImpl repository; - private JcrFileSystem fileSystem; - - private Credentials credentials; - - public JackrabbitMemoryFsProvider() { - String username = System.getProperty("user.name"); - credentials = new SimpleCredentials(username, username.toCharArray()); - } - - @Override - public String getScheme() { - return "jcr+memory"; - } - - @Override - public FileSystem newFileSystem(URI uri, Map env) throws IOException { - try { - Path tempDir = Files.createTempDirectory("fs-memory"); - URL confUrl = JackrabbitMemoryFsProvider.class.getResource("fs-memory.xml"); - RepositoryConfig repositoryConfig = RepositoryConfig.create(confUrl.toURI(), tempDir.toString()); - repository = RepositoryImpl.create(repositoryConfig); - postRepositoryCreation(repository); - fileSystem = new JcrFileSystem(this, repository, credentials); - return fileSystem; - } catch (RepositoryException | URISyntaxException e) { - throw new IOException("Cannot login to repository", e); - } - } - - @Override - public FileSystem getFileSystem(URI uri) { - return fileSystem; - } - - @Override - public Path getPath(URI uri) { - String path = uri.getPath(); - if (fileSystem == null) - try { - newFileSystem(uri, new HashMap()); - } catch (IOException e) { - throw new JcrFsException("Could not autocreate file system", e); - } - return fileSystem.getPath(path); - } - - public Repository getRepository() { - return repository; - } - - public Session login() throws RepositoryException { - return getRepository().login(credentials); - } - - /** - * Called after the repository has been created and before the file system is - * created. - */ - protected void postRepositoryCreation(RepositoryImpl repositoryImpl) throws RepositoryException { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/fs-memory.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/fs-memory.xml deleted file mode 100644 index f2541fb4e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/fs-memory.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/package-info.java deleted file mode 100644 index c9ec2c3b9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/fs/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Java NIO file system implementation based on Jackrabbit. */ -package org.argeo.jackrabbit.fs; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/package-info.java deleted file mode 100644 index 17497d62c..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic Jackrabbit utilities. */ -package org.argeo.jackrabbit; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-h2.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-h2.xml deleted file mode 100644 index 05267621f..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-h2.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-localfs.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-localfs.xml deleted file mode 100644 index 3d2470863..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-localfs.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-memory.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-memory.xml deleted file mode 100644 index ecee5bdad..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-memory.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql-ds.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql-ds.xml deleted file mode 100644 index 07a0d0428..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql-ds.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql.xml b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql.xml deleted file mode 100644 index 967782820..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/repository-postgresql.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/JackrabbitSecurityUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/JackrabbitSecurityUtils.java deleted file mode 100644 index f98cf9947..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/JackrabbitSecurityUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.argeo.jackrabbit.security; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager; -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.JcrUtils; - -/** Utilities around Jackrabbit security extensions. */ -public class JackrabbitSecurityUtils { - private final static CmsLog log = CmsLog.getLog(JackrabbitSecurityUtils.class); - - /** - * Convenience method for denying a single privilege to a principal (user or - * role), typically jcr:all - */ - public synchronized static void denyPrivilege(Session session, String path, String principal, String privilege) - throws RepositoryException { - List privileges = new ArrayList(); - privileges.add(session.getAccessControlManager().privilegeFromName(privilege)); - denyPrivileges(session, path, () -> principal, privileges); - } - - /** - * Deny privileges on a path to a {@link Principal}. The path must already - * exist. Session is saved. Synchronized to prevent concurrent modifications of - * the same node. - */ - public synchronized static Boolean denyPrivileges(Session session, String path, Principal principal, - List privs) throws RepositoryException { - // make sure the session is in line with the persisted state - session.refresh(false); - JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) session.getAccessControlManager(); - JackrabbitAccessControlList acl = (JackrabbitAccessControlList) JcrUtils.getAccessControlList(acm, path); - -// accessControlEntries: for (AccessControlEntry ace : acl.getAccessControlEntries()) { -// Principal currentPrincipal = ace.getPrincipal(); -// if (currentPrincipal.getName().equals(principal.getName())) { -// Privilege[] currentPrivileges = ace.getPrivileges(); -// if (currentPrivileges.length != privs.size()) -// break accessControlEntries; -// for (int i = 0; i < currentPrivileges.length; i++) { -// Privilege currP = currentPrivileges[i]; -// Privilege p = privs.get(i); -// if (!currP.getName().equals(p.getName())) { -// break accessControlEntries; -// } -// } -// return false; -// } -// } - - Privilege[] privileges = privs.toArray(new Privilege[privs.size()]); - acl.addEntry(principal, privileges, false); - acm.setPolicy(path, acl); - if (log.isDebugEnabled()) { - StringBuffer privBuf = new StringBuffer(); - for (Privilege priv : privs) - privBuf.append(priv.getName()); - log.debug("Denied privileges " + privBuf + " to " + principal.getName() + " on " + path + " in '" - + session.getWorkspace().getName() + "'"); - } - session.refresh(true); - session.save(); - return true; - } - - /** Singleton. */ - private JackrabbitSecurityUtils() { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/package-info.java deleted file mode 100644 index f3a282c4e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jackrabbit/security/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic Jackrabbit security utilities. */ -package org.argeo.jackrabbit.security; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Bin.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Bin.java deleted file mode 100644 index 0418810ed..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Bin.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.argeo.jcr; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.Binary; -import javax.jcr.Property; -import javax.jcr.RepositoryException; - -/** - * A {@link Binary} wrapper implementing {@link AutoCloseable} for ease of use - * in try/catch blocks. - */ -public class Bin implements Binary, AutoCloseable { - private final Binary wrappedBinary; - - public Bin(Property property) throws RepositoryException { - this(property.getBinary()); - } - - public Bin(Binary wrappedBinary) { - if (wrappedBinary == null) - throw new IllegalArgumentException("Wrapped binary cannot be null"); - this.wrappedBinary = wrappedBinary; - } - - // private static Binary getBinary(Property property) throws IOException { - // try { - // return property.getBinary(); - // } catch (RepositoryException e) { - // throw new IOException("Cannot get binary from property " + property, e); - // } - // } - - @Override - public void close() { - dispose(); - } - - @Override - public InputStream getStream() throws RepositoryException { - return wrappedBinary.getStream(); - } - - @Override - public int read(byte[] b, long position) throws IOException, RepositoryException { - return wrappedBinary.read(b, position); - } - - @Override - public long getSize() throws RepositoryException { - return wrappedBinary.getSize(); - } - - @Override - public void dispose() { - wrappedBinary.dispose(); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/CollectionNodeIterator.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/CollectionNodeIterator.java deleted file mode 100644 index b4124eea5..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/CollectionNodeIterator.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.argeo.jcr; - -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; - -/** Wraps a collection of nodes in order to read it as a {@link NodeIterator} */ -public class CollectionNodeIterator implements NodeIterator { - private final Long collectionSize; - private final Iterator iterator; - private Integer position = 0; - - public CollectionNodeIterator(Collection nodes) { - super(); - this.collectionSize = (long) nodes.size(); - this.iterator = nodes.iterator(); - } - - public void skip(long skipNum) { - if (skipNum < 0) - throw new IllegalArgumentException( - "Skip count has to be positive: " + skipNum); - - for (long i = 0; i < skipNum; i++) { - if (!hasNext()) - throw new NoSuchElementException("Last element past (position=" - + getPosition() + ")"); - nextNode(); - } - } - - public long getSize() { - return collectionSize; - } - - public long getPosition() { - return position; - } - - public boolean hasNext() { - return iterator.hasNext(); - } - - public Object next() { - return nextNode(); - } - - public void remove() { - iterator.remove(); - } - - public Node nextNode() { - Node node = iterator.next(); - position++; - return node; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/DefaultJcrListener.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/DefaultJcrListener.java deleted file mode 100644 index d873ef652..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/DefaultJcrListener.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.argeo.jcr; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; - -import org.argeo.api.cms.CmsLog; - -/** To be overridden */ -public class DefaultJcrListener implements EventListener { - private final static CmsLog log = CmsLog.getLog(DefaultJcrListener.class); - private Session session; - private String path = "/"; - private Boolean deep = true; - - public void start() { - try { - addEventListener(session().getWorkspace().getObservationManager()); - if (log.isDebugEnabled()) - log.debug("Registered JCR event listener on " + path); - } catch (RepositoryException e) { - throw new JcrException("Cannot register event listener", e); - } - } - - public void stop() { - try { - session().getWorkspace().getObservationManager() - .removeEventListener(this); - if (log.isDebugEnabled()) - log.debug("Unregistered JCR event listener on " + path); - } catch (RepositoryException e) { - throw new JcrException("Cannot unregister event listener", e); - } - } - - /** Default is listen to all events */ - protected Integer getEvents() { - return Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED - | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED; - } - - /** To be overidden */ - public void onEvent(EventIterator events) { - while (events.hasNext()) { - Event event = events.nextEvent(); - log.debug(event); - } - } - - /** To be overidden */ - protected void addEventListener(ObservationManager observationManager) - throws RepositoryException { - observationManager.addEventListener(this, getEvents(), path, deep, - null, null, false); - } - - private Session session() { - return session; - } - - public void setPath(String path) { - this.path = path; - } - - public void setDeep(Boolean deep) { - this.deep = deep; - } - - public void setSession(Session session) { - this.session = session; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Jcr.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Jcr.java deleted file mode 100644 index 49b008d70..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/Jcr.java +++ /dev/null @@ -1,993 +0,0 @@ -package org.argeo.jcr; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.text.MessageFormat; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Iterator; -import java.util.List; - -import javax.jcr.Binary; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.Workspace; -import javax.jcr.nodetype.NodeType; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; -import javax.jcr.query.Row; -import javax.jcr.security.Privilege; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.VersionManager; - -import org.apache.commons.io.IOUtils; - -/** - * Utility class whose purpose is to make using JCR less verbose by - * systematically using unchecked exceptions and returning null - * when something is not found. This is especially useful when writing user - * interfaces (such as with SWT) where listeners and callbacks expect unchecked - * exceptions. Loosely inspired by Java's Files singleton. - */ -public class Jcr { - /** - * The name of a node which will be serialized as XML text, as per section 7.3.1 - * of the JCR 2.0 specifications. - */ - public final static String JCR_XMLTEXT = "jcr:xmltext"; - /** - * The name of a property which will be serialized as XML text, as per section - * 7.3.1 of the JCR 2.0 specifications. - */ - public final static String JCR_XMLCHARACTERS = "jcr:xmlcharacters"; - /** - * jcr:name, when used in another context than - * {@link Property#JCR_NAME}, typically to name a node rather than a property. - */ - public final static String JCR_NAME = "jcr:name"; - /** - * jcr:path, when used in another context than - * {@link Property#JCR_PATH}, typically to name a node rather than a property. - */ - public final static String JCR_PATH = "jcr:path"; - /** - * jcr:primaryType with prefix instead of namespace (as in - * {@link Property#JCR_PRIMARY_TYPE}. - */ - public final static String JCR_PRIMARY_TYPE = "jcr:primaryType"; - /** - * jcr:mixinTypes with prefix instead of namespace (as in - * {@link Property#JCR_MIXIN_TYPES}. - */ - public final static String JCR_MIXIN_TYPES = "jcr:mixinTypes"; - /** - * jcr:uuid with prefix instead of namespace (as in - * {@link Property#JCR_UUID}. - */ - public final static String JCR_UUID = "jcr:uuid"; - /** - * jcr:created with prefix instead of namespace (as in - * {@link Property#JCR_CREATED}. - */ - public final static String JCR_CREATED = "jcr:created"; - /** - * jcr:createdBy with prefix instead of namespace (as in - * {@link Property#JCR_CREATED_BY}. - */ - public final static String JCR_CREATED_BY = "jcr:createdBy"; - /** - * jcr:lastModified with prefix instead of namespace (as in - * {@link Property#JCR_LAST_MODIFIED}. - */ - public final static String JCR_LAST_MODIFIED = "jcr:lastModified"; - /** - * jcr:lastModifiedBy with prefix instead of namespace (as in - * {@link Property#JCR_LAST_MODIFIED_BY}. - */ - public final static String JCR_LAST_MODIFIED_BY = "jcr:lastModifiedBy"; - - /** - * @see Node#isNodeType(String) - * @throws JcrException caused by {@link RepositoryException} - */ - public static boolean isNodeType(Node node, String nodeTypeName) { - try { - return node.isNodeType(nodeTypeName); - } catch (RepositoryException e) { - throw new JcrException("Cannot get whether " + node + " is of type " + nodeTypeName, e); - } - } - - /** - * @see Node#hasNodes() - * @throws JcrException caused by {@link RepositoryException} - */ - public static boolean hasNodes(Node node) { - try { - return node.hasNodes(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get whether " + node + " has children.", e); - } - } - - /** - * @see Node#getParent() - * @throws JcrException caused by {@link RepositoryException} - */ - public static Node getParent(Node node) { - try { - return isRoot(node) ? null : node.getParent(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get parent of " + node, e); - } - } - - /** - * @see Node#getParent() - * @throws JcrException caused by {@link RepositoryException} - */ - public static String getParentPath(Node node) { - return getPath(getParent(node)); - } - - /** - * Whether this node is the root node. - * - * @throws JcrException caused by {@link RepositoryException} - */ - public static boolean isRoot(Node node) { - try { - return node.getDepth() == 0; - } catch (RepositoryException e) { - throw new JcrException("Cannot get depth of " + node, e); - } - } - - /** - * @see Node#getPath() - * @throws JcrException caused by {@link RepositoryException} - */ - public static String getPath(Node node) { - try { - return node.getPath(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get path of " + node, e); - } - } - - /** - * @see Node#getSession() - * @see Session#getWorkspace() - * @see Workspace#getName() - */ - public static String getWorkspaceName(Node node) { - return session(node).getWorkspace().getName(); - } - - /** - * @see Node#getIdentifier() - * @throws JcrException caused by {@link RepositoryException} - */ - public static String getIdentifier(Node node) { - try { - return node.getIdentifier(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get identifier of " + node, e); - } - } - - /** - * @see Node#getName() - * @throws JcrException caused by {@link RepositoryException} - */ - public static String getName(Node node) { - try { - return node.getName(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get name of " + node, e); - } - } - - /** - * Returns the node name with its current index (useful for re-ordering). - * - * @see Node#getName() - * @see Node#getIndex() - * @throws JcrException caused by {@link RepositoryException} - */ - public static String getIndexedName(Node node) { - try { - return node.getName() + "[" + node.getIndex() + "]"; - } catch (RepositoryException e) { - throw new JcrException("Cannot get name of " + node, e); - } - } - - /** - * @see Node#getProperty(String) - * @throws JcrException caused by {@link RepositoryException} - */ - public static Property getProperty(Node node, String property) { - try { - if (node.hasProperty(property)) - return node.getProperty(property); - else - return null; - } catch (RepositoryException e) { - throw new JcrException("Cannot get property " + property + " of " + node, e); - } - } - - /** - * @see Node#getIndex() - * @throws JcrException caused by {@link RepositoryException} - */ - public static int getIndex(Node node) { - try { - return node.getIndex(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get index of " + node, e); - } - } - - /** - * If node has mixin {@link NodeType#MIX_TITLE}, return - * {@link Property#JCR_TITLE}, otherwise return {@link #getName(Node)}. - */ - public static String getTitle(Node node) { - if (Jcr.isNodeType(node, NodeType.MIX_TITLE)) - return get(node, Property.JCR_TITLE); - else - return Jcr.getName(node); - } - - /** Accesses a {@link NodeIterator} as an {@link Iterable}. */ - @SuppressWarnings("unchecked") - public static Iterable iterate(NodeIterator nodeIterator) { - return new Iterable() { - - @Override - public Iterator iterator() { - return nodeIterator; - } - }; - } - - /** - * @return the children as an {@link Iterable} for use in for-each llops. - * @see Node#getNodes() - * @throws JcrException caused by {@link RepositoryException} - */ - public static Iterable nodes(Node node) { - try { - return iterate(node.getNodes()); - } catch (RepositoryException e) { - throw new JcrException("Cannot get children of " + node, e); - } - } - - /** - * @return the children as a (possibly empty) {@link List}. - * @see Node#getNodes() - * @throws JcrException caused by {@link RepositoryException} - */ - public static List getNodes(Node node) { - List nodes = new ArrayList<>(); - try { - if (node.hasNodes()) { - NodeIterator nit = node.getNodes(); - while (nit.hasNext()) - nodes.add(nit.nextNode()); - return nodes; - } else - return nodes; - } catch (RepositoryException e) { - throw new JcrException("Cannot get children of " + node, e); - } - } - - /** - * @return the child or null if not found - * @see Node#getNode(String) - * @throws JcrException caused by {@link RepositoryException} - */ - public static Node getNode(Node node, String child) { - try { - if (node.hasNode(child)) - return node.getNode(child); - else - return null; - } catch (RepositoryException e) { - throw new JcrException("Cannot get child of " + node, e); - } - } - - /** - * @return the node at this path or null if not found - * @see Session#getNode(String) - * @throws JcrException caused by {@link RepositoryException} - */ - public static Node getNode(Session session, String path) { - try { - if (session.nodeExists(path)) - return session.getNode(path); - else - return null; - } catch (RepositoryException e) { - throw new JcrException("Cannot get node " + path, e); - } - } - - /** - * Add a node to this parent, setting its primary type and its mixins. - * - * @param parent the parent node - * @param name the name of the node, if null, the primary - * type will be used (typically for XML structures) - * @param primaryType the primary type, if null - * {@link NodeType#NT_UNSTRUCTURED} will be used. - * @param mixins the mixins - * @return the created node - * @see Node#addNode(String, String) - * @see Node#addMixin(String) - */ - public static Node addNode(Node parent, String name, String primaryType, String... mixins) { - if (name == null && primaryType == null) - throw new IllegalArgumentException("Both node name and primary type cannot be null"); - try { - Node newNode = parent.addNode(name == null ? primaryType : name, - primaryType == null ? NodeType.NT_UNSTRUCTURED : primaryType); - for (String mixin : mixins) { - newNode.addMixin(mixin); - } - return newNode; - } catch (RepositoryException e) { - throw new JcrException("Cannot add node " + name + " to " + parent, e); - } - } - - /** - * Add an {@link NodeType#NT_BASE} node to this parent. - * - * @param parent the parent node - * @param name the name of the node, cannot be null - * @return the created node - * - * @see Node#addNode(String) - */ - public static Node addNode(Node parent, String name) { - if (name == null) - throw new IllegalArgumentException("Node name cannot be null"); - try { - Node newNode = parent.addNode(name); - return newNode; - } catch (RepositoryException e) { - throw new JcrException("Cannot add node " + name + " to " + parent, e); - } - } - - /** - * Add mixins to a node. - * - * @param node the node - * @param mixins the mixins - * @see Node#addMixin(String) - */ - public static void addMixin(Node node, String... mixins) { - try { - for (String mixin : mixins) { - node.addMixin(mixin); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot add mixins " + Arrays.asList(mixins) + " to " + node, e); - } - } - - /** - * Removes this node. - * - * @see Node#remove() - */ - public static void remove(Node node) { - try { - node.remove(); - } catch (RepositoryException e) { - throw new JcrException("Cannot remove node " + node, e); - } - } - - /** - * @return the node with htis id or null if not found - * @see Session#getNodeByIdentifier(String) - * @throws JcrException caused by {@link RepositoryException} - */ - public static Node getNodeById(Session session, String id) { - try { - return session.getNodeByIdentifier(id); - } catch (ItemNotFoundException e) { - return null; - } catch (RepositoryException e) { - throw new JcrException("Cannot get node with id " + id, e); - } - } - - /** - * Set a property to the given value, or remove it if the value is - * null. - * - * @throws JcrException caused by {@link RepositoryException} - */ - public static void set(Node node, String property, Object value) { - try { - if (!node.hasProperty(property)) { - if (value != null) { - if (value instanceof List) {// multiple - List lst = (List) value; - String[] values = new String[lst.size()]; - for (int i = 0; i < lst.size(); i++) { - values[i] = lst.get(i).toString(); - } - node.setProperty(property, values); - } else { - node.setProperty(property, value.toString()); - } - } - return; - } - Property prop = node.getProperty(property); - if (value == null) { - prop.remove(); - return; - } - - // multiple - if (value instanceof List) { - List lst = (List) value; - String[] values = new String[lst.size()]; - // TODO better cast? - for (int i = 0; i < lst.size(); i++) { - values[i] = lst.get(i).toString(); - } - if (!prop.isMultiple()) - prop.remove(); - node.setProperty(property, values); - return; - } - - // single - if (prop.isMultiple()) { - prop.remove(); - node.setProperty(property, value.toString()); - return; - } - - if (value instanceof String) - prop.setValue((String) value); - else if (value instanceof Long) - prop.setValue((Long) value); - else if (value instanceof Integer) - prop.setValue(((Integer) value).longValue()); - else if (value instanceof Double) - prop.setValue((Double) value); - else if (value instanceof Float) - prop.setValue(((Float) value).doubleValue()); - else if (value instanceof Calendar) - prop.setValue((Calendar) value); - else if (value instanceof BigDecimal) - prop.setValue((BigDecimal) value); - else if (value instanceof Boolean) - prop.setValue((Boolean) value); - else if (value instanceof byte[]) - JcrUtils.setBinaryAsBytes(prop, (byte[]) value); - else if (value instanceof Instant) { - Instant instant = (Instant) value; - GregorianCalendar calendar = new GregorianCalendar(); - calendar.setTime(Date.from(instant)); - prop.setValue(calendar); - } else // try with toString() - prop.setValue(value.toString()); - } catch (RepositoryException e) { - throw new JcrException("Cannot set property " + property + " of " + node + " to " + value, e); - } - } - - /** - * Get property as {@link String}. - * - * @return the value of - * {@link Node#getProperty(String)}.{@link Property#getString()} or - * null if the property does not exist. - * @throws JcrException caused by {@link RepositoryException} - */ - public static String get(Node node, String property) { - return get(node, property, null); - } - - /** - * Get property as a {@link String}. If the property is multiple it returns the - * first value. - * - * @return the value of - * {@link Node#getProperty(String)}.{@link Property#getString()} or - * defaultValue if the property does not exist. - * @throws JcrException caused by {@link RepositoryException} - */ - public static String get(Node node, String property, String defaultValue) { - try { - if (node.hasProperty(property)) { - Property p = node.getProperty(property); - if (!p.isMultiple()) - return p.getString(); - else { - Value[] values = p.getValues(); - if (values.length == 0) - return defaultValue; - else - return values[0].getString(); - } - } else - return defaultValue; - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve property " + property + " from " + node, e); - } - } - - /** - * Get property as a {@link Value}. - * - * @return {@link Node#getProperty(String)} or null if the property - * does not exist. - * @throws JcrException caused by {@link RepositoryException} - */ - public static Value getValue(Node node, String property) { - try { - if (node.hasProperty(property)) - return node.getProperty(property).getValue(); - else - return null; - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve property " + property + " from " + node, e); - } - } - - /** - * Get property doing a best effort to cast it as the target object. - * - * @return the value of {@link Node#getProperty(String)} or - * defaultValue if the property does not exist. - * @throws IllegalArgumentException if the value could not be cast - * @throws JcrException in case of unexpected - * {@link RepositoryException} - */ - @SuppressWarnings("unchecked") - public static T getAs(Node node, String property, T defaultValue) { - try { - // TODO deal with multiple - if (node.hasProperty(property)) { - Property p = node.getProperty(property); - try { - if (p.isMultiple()) { - throw new UnsupportedOperationException("Multiple values properties are not supported"); - } - Value value = p.getValue(); - return (T) get(value); - } catch (ClassCastException e) { - throw new IllegalArgumentException( - "Cannot cast property of type " + PropertyType.nameFromValue(p.getType()), e); - } - } else { - return defaultValue; - } - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve property " + property + " from " + node, e); - } - } - - public static T getAs(Node node, String property, Class clss) { - if (String.class.isAssignableFrom(clss)) { - return (T) get(node, property); - } else if (Long.class.isAssignableFrom(clss)) { - return (T) get(node, property); - } else { - throw new IllegalArgumentException("Unsupported format " + clss); - } - } - - /** - * Get a multiple property as a list, doing a best effort to cast it as the - * target list. - * - * @return the value of {@link Node#getProperty(String)}. - * @throws IllegalArgumentException if the value could not be cast - * @throws JcrException in case of unexpected - * {@link RepositoryException} - */ - public static List getMultiple(Node node, String property) { - try { - if (node.hasProperty(property)) { - Property p = node.getProperty(property); - return getMultiple(p); - } else { - return null; - } - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve multiple values property " + property + " from " + node, e); - } - } - - /** - * Get a multiple property as a list, doing a best effort to cast it as the - * target list. - */ - @SuppressWarnings("unchecked") - public static List getMultiple(Property p) { - try { - List res = new ArrayList<>(); - if (!p.isMultiple()) { - res.add((T) get(p.getValue())); - return res; - } - Value[] values = p.getValues(); - for (Value value : values) { - res.add((T) get(value)); - } - return res; - } catch (ClassCastException | RepositoryException e) { - throw new IllegalArgumentException("Cannot get property " + p, e); - } - } - - /** Cast a {@link Value} to a standard Java object. */ - public static Object get(Value value) { - Binary binary = null; - try { - switch (value.getType()) { - case PropertyType.STRING: - return value.getString(); - case PropertyType.DOUBLE: - return (Double) value.getDouble(); - case PropertyType.LONG: - return (Long) value.getLong(); - case PropertyType.BOOLEAN: - return (Boolean) value.getBoolean(); - case PropertyType.DATE: - return value.getDate(); - case PropertyType.BINARY: - binary = value.getBinary(); - byte[] arr = null; - try (InputStream in = binary.getStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();) { - IOUtils.copy(in, out); - arr = out.toByteArray(); - } catch (IOException e) { - throw new RuntimeException("Cannot read binary from " + value, e); - } - return arr; - default: - return value.getString(); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot cast value from " + value, e); - } finally { - if (binary != null) - binary.dispose(); - } - } - - /** - * Retrieves the {@link Session} related to this node. - * - * @deprecated Use {@link #getSession(Node)} instead. - */ - @Deprecated - public static Session session(Node node) { - return getSession(node); - } - - /** Retrieves the {@link Session} related to this node. */ - public static Session getSession(Node node) { - try { - return node.getSession(); - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve session related to " + node, e); - } - } - - /** Retrieves the root node related to this session. */ - public static Node getRootNode(Session session) { - try { - return session.getRootNode(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get root node for " + session, e); - } - } - - /** Whether this item exists. */ - public static boolean itemExists(Session session, String path) { - try { - return session.itemExists(path); - } catch (RepositoryException e) { - throw new JcrException("Cannot check whether " + path + " exists", e); - } - } - - /** - * Saves the {@link Session} related to this node. Note that all other unrelated - * modifications in this session will also be saved. - */ - public static void save(Node node) { - try { - Session session = node.getSession(); -// if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) { -// set(node, Property.JCR_LAST_MODIFIED, Instant.now()); -// set(node, Property.JCR_LAST_MODIFIED_BY, session.getUserID()); -// } - if (session.hasPendingChanges()) - session.save(); - } catch (RepositoryException e) { - throw new JcrException("Cannot save session related to " + node + " in workspace " - + session(node).getWorkspace().getName(), e); - } - } - - /** Login to a JCR repository. */ - public static Session login(Repository repository, String workspace) { - try { - return repository.login(workspace); - } catch (RepositoryException e) { - throw new IllegalArgumentException("Cannot login to repository", e); - } - } - - /** Safely and silently logs out a session. */ - public static void logout(Session session) { - try { - if (session != null) - if (session.isLive()) - session.logout(); - } catch (Exception e) { - // silent - } - } - - /** Safely and silently logs out the underlying session. */ - public static void logout(Node node) { - Jcr.logout(session(node)); - } - - /* - * SECURITY - */ - /** - * Add a single privilege to a node. - * - * @see Privilege - */ - public static void addPrivilege(Node node, String principal, String privilege) { - try { - Session session = node.getSession(); - JcrUtils.addPrivilege(session, node.getPath(), principal, privilege); - } catch (RepositoryException e) { - throw new JcrException("Cannot add privilege " + privilege + " to " + node, e); - } - } - - /* - * VERSIONING - */ - /** Get checked out status. */ - public static boolean isCheckedOut(Node node) { - try { - return node.isCheckedOut(); - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve checked out status of " + node, e); - } - } - - /** @see VersionManager#checkpoint(String) */ - public static void checkpoint(Node node) { - try { - versionManager(node).checkpoint(node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot check in " + node, e); - } - } - - /** @see VersionManager#checkin(String) */ - public static void checkin(Node node) { - try { - versionManager(node).checkin(node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot check in " + node, e); - } - } - - /** @see VersionManager#checkout(String) */ - public static void checkout(Node node) { - try { - versionManager(node).checkout(node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot check out " + node, e); - } - } - - /** Get the {@link VersionManager} related to this node. */ - public static VersionManager versionManager(Node node) { - try { - return node.getSession().getWorkspace().getVersionManager(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get version manager from " + node, e); - } - } - - /** Get the {@link VersionHistory} related to this node. */ - public static VersionHistory getVersionHistory(Node node) { - try { - return versionManager(node).getVersionHistory(node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot get version history from " + node, e); - } - } - - /** - * The linear versions of this version history in reverse order and without the - * root version. - */ - public static List getLinearVersions(VersionHistory versionHistory) { - try { - List lst = new ArrayList<>(); - VersionIterator vit = versionHistory.getAllLinearVersions(); - while (vit.hasNext()) - lst.add(vit.nextVersion()); - lst.remove(0); - Collections.reverse(lst); - return lst; - } catch (RepositoryException e) { - throw new JcrException("Cannot get linear versions from " + versionHistory, e); - } - } - - /** The frozen node related to this {@link Version}. */ - public static Node getFrozenNode(Version version) { - try { - return version.getFrozenNode(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get frozen node from " + version, e); - } - } - - /** Get the base {@link Version} related to this node. */ - public static Version getBaseVersion(Node node) { - try { - return versionManager(node).getBaseVersion(node.getPath()); - } catch (RepositoryException e) { - throw new JcrException("Cannot get base version from " + node, e); - } - } - - /* - * FILES - */ - /** - * Returns the size of this file. - * - * @see NodeType#NT_FILE - */ - public static long getFileSize(Node fileNode) { - try { - if (!fileNode.isNodeType(NodeType.NT_FILE)) - throw new IllegalArgumentException(fileNode + " must be a file."); - return getBinarySize(fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary()); - } catch (RepositoryException e) { - throw new JcrException("Cannot get file size of " + fileNode, e); - } - } - - /** Returns the size of this {@link Binary}. */ - public static long getBinarySize(Binary binaryArg) { - try { - try (Bin binary = new Bin(binaryArg)) { - return binary.getSize(); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot get file size of binary " + binaryArg, e); - } - } - - // QUERY - /** Creates a JCR-SQL2 query using {@link MessageFormat}. */ - public static Query createQuery(QueryManager qm, String sql, Object... args) { - // fix single quotes - sql = sql.replaceAll("'", "''"); - String query = MessageFormat.format(sql, args); - try { - return qm.createQuery(query, Query.JCR_SQL2); - } catch (RepositoryException e) { - throw new JcrException("Cannot create JCR-SQL2 query from " + query, e); - } - } - - /** Executes a JCR-SQL2 query using {@link MessageFormat}. */ - public static NodeIterator executeQuery(QueryManager qm, String sql, Object... args) { - Query query = createQuery(qm, sql, args); - try { - return query.execute().getNodes(); - } catch (RepositoryException e) { - throw new JcrException("Cannot execute query " + sql + " with arguments " + Arrays.asList(args), e); - } - } - - /** Executes a JCR-SQL2 query using {@link MessageFormat}. */ - public static NodeIterator executeQuery(Session session, String sql, Object... args) { - QueryManager queryManager; - try { - queryManager = session.getWorkspace().getQueryManager(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get query manager from session " + session, e); - } - return executeQuery(queryManager, sql, args); - } - - /** - * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a - * single node at most. - * - * @return the node or null if not found. - */ - public static Node getNode(QueryManager qm, String sql, Object... args) { - NodeIterator nit = executeQuery(qm, sql, args); - if (nit.hasNext()) { - Node node = nit.nextNode(); - if (nit.hasNext()) - throw new IllegalStateException( - "Query " + sql + " with arguments " + Arrays.asList(args) + " returned more than one node."); - return node; - } else { - return null; - } - } - - /** - * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a - * single node at most. - * - * @return the node or null if not found. - */ - public static Node getNode(Session session, String sql, Object... args) { - QueryManager queryManager; - try { - queryManager = session.getWorkspace().getQueryManager(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get query manager from session " + session, e); - } - return getNode(queryManager, sql, args); - } - - public static Node getRowNode(Row row, String selectorName) { - try { - return row.getNode(selectorName); - } catch (RepositoryException e) { - throw new JcrException("Cannot get node " + selectorName + " from row", e); - } - } - - /** Singleton. */ - private Jcr() { - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrAuthorizations.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrAuthorizations.java deleted file mode 100644 index 351929f8d..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrAuthorizations.java +++ /dev/null @@ -1,207 +0,0 @@ -package org.argeo.jcr; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.Privilege; -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; - -/** Apply authorizations to a JCR repository. */ -public class JcrAuthorizations implements Runnable { - // private final static Log log = - // LogFactory.getLog(JcrAuthorizations.class); - - private Repository repository; - private String workspace = null; - - private String securityWorkspace = "security"; - - /** - * key := privilege1,privilege2/path/to/node
- * value := group1,group2,user1 - */ - private Map principalPrivileges = new HashMap(); - - public void run() { - String currentWorkspace = workspace; - Session session = null; - try { - if (workspace != null && workspace.equals("*")) { - session = repository.login(); - String[] workspaces = session.getWorkspace().getAccessibleWorkspaceNames(); - JcrUtils.logoutQuietly(session); - for (String wksp : workspaces) { - currentWorkspace = wksp; - if (currentWorkspace.equals(securityWorkspace)) - continue; - session = repository.login(currentWorkspace); - initAuthorizations(session); - JcrUtils.logoutQuietly(session); - } - } else { - session = repository.login(workspace); - initAuthorizations(session); - } - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new JcrException( - "Cannot set authorizations " + principalPrivileges + " on workspace " + currentWorkspace, e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - protected void processWorkspace(String workspace) { - Session session = null; - try { - session = repository.login(workspace); - initAuthorizations(session); - } catch (RepositoryException e) { - JcrUtils.discardQuietly(session); - throw new JcrException( - "Cannot set authorizations " + principalPrivileges + " on repository " + repository, e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - /** @deprecated call {@link #run()} instead. */ - @Deprecated - public void init() { - run(); - } - - protected void initAuthorizations(Session session) throws RepositoryException { - AccessControlManager acm = session.getAccessControlManager(); - - for (String privileges : principalPrivileges.keySet()) { - String path = null; - int slashIndex = privileges.indexOf('/'); - if (slashIndex == 0) { - throw new IllegalArgumentException("Privilege " + privileges + " badly formatted it starts with /"); - } else if (slashIndex > 0) { - path = privileges.substring(slashIndex); - privileges = privileges.substring(0, slashIndex); - } - - if (path == null) - path = "/"; - - List privs = new ArrayList(); - for (String priv : privileges.split(",")) { - privs.add(acm.privilegeFromName(priv)); - } - - String principalNames = principalPrivileges.get(privileges); - try { - new LdapName(principalNames); - // TODO differentiate groups and users ? - Principal principal = getOrCreatePrincipal(session, principalNames); - JcrUtils.addPrivileges(session, path, principal, privs); - } catch (InvalidNameException e) { - for (String principalName : principalNames.split(",")) { - Principal principal = getOrCreatePrincipal(session, principalName); - JcrUtils.addPrivileges(session, path, principal, privs); - // if (log.isDebugEnabled()) { - // StringBuffer privBuf = new StringBuffer(); - // for (Privilege priv : privs) - // privBuf.append(priv.getName()); - // log.debug("Added privileges " + privBuf + " to " - // + principal.getName() + " on " + path + " in '" - // + session.getWorkspace().getName() + "'"); - // } - } - } - } - - // if (log.isDebugEnabled()) - // log.debug("JCR authorizations applied on '" - // + session.getWorkspace().getName() + "'"); - } - - /** - * Returns a {@link SimplePrincipal}, does not check whether it exists since - * such capabilities is not provided by the standard JCR API. Can be - * overridden to provide smarter handling - */ - protected Principal getOrCreatePrincipal(Session session, String principalName) throws RepositoryException { - return new SimplePrincipal(principalName); - } - - // public static void addPrivileges(Session session, Principal principal, - // String path, List privs) throws RepositoryException { - // AccessControlManager acm = session.getAccessControlManager(); - // // search for an access control list - // AccessControlList acl = null; - // AccessControlPolicyIterator policyIterator = acm - // .getApplicablePolicies(path); - // if (policyIterator.hasNext()) { - // while (policyIterator.hasNext()) { - // AccessControlPolicy acp = policyIterator - // .nextAccessControlPolicy(); - // if (acp instanceof AccessControlList) - // acl = ((AccessControlList) acp); - // } - // } else { - // AccessControlPolicy[] existingPolicies = acm.getPolicies(path); - // for (AccessControlPolicy acp : existingPolicies) { - // if (acp instanceof AccessControlList) - // acl = ((AccessControlList) acp); - // } - // } - // - // if (acl != null) { - // acl.addAccessControlEntry(principal, - // privs.toArray(new Privilege[privs.size()])); - // acm.setPolicy(path, acl); - // session.save(); - // if (log.isDebugEnabled()) { - // StringBuffer buf = new StringBuffer(""); - // for (int i = 0; i < privs.size(); i++) { - // if (i != 0) - // buf.append(','); - // buf.append(privs.get(i).getName()); - // } - // log.debug("Added privilege(s) '" + buf + "' to '" - // + principal.getName() + "' on " + path - // + " from workspace '" - // + session.getWorkspace().getName() + "'"); - // } - // } else { - // throw new ArgeoJcrException("Don't know how to apply privileges " - // + privs + " to " + principal + " on " + path - // + " from workspace '" + session.getWorkspace().getName() - // + "'"); - // } - // } - - @Deprecated - public void setGroupPrivileges(Map groupPrivileges) { - this.principalPrivileges = groupPrivileges; - } - - public void setPrincipalPrivileges(Map principalPrivileges) { - this.principalPrivileges = principalPrivileges; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setWorkspace(String workspace) { - this.workspace = workspace; - } - - public void setSecurityWorkspace(String securityWorkspace) { - this.securityWorkspace = securityWorkspace; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrCallback.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrCallback.java deleted file mode 100644 index efbaabe82..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrCallback.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.argeo.jcr; - -import java.util.function.Function; - -import javax.jcr.Session; - -/** An arbitrary execution on a JCR session, optionally returning a result. */ -@FunctionalInterface -public interface JcrCallback extends Function { - /** @deprecated Use {@link #apply(Session)} instead. */ - @Deprecated - public default Object execute(Session session) { - return apply(session); - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrException.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrException.java deleted file mode 100644 index c77874376..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.argeo.jcr; - -import javax.jcr.RepositoryException; - -/** - * Wraps a {@link RepositoryException} in a {@link RuntimeException}. - */ -public class JcrException extends IllegalStateException { - private static final long serialVersionUID = -4530350094877964989L; - - public JcrException(String message, RepositoryException e) { - super(message, e); - } - - public JcrException(RepositoryException e) { - super(e); - } - - public RepositoryException getRepositoryCause() { - return (RepositoryException) getCause(); - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrMonitor.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrMonitor.java deleted file mode 100644 index 71cf961e0..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrMonitor.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.argeo.jcr; - - -/** - * Simple monitor abstraction. Inspired by Eclipse IProgressMOnitor, but without - * dependency to it. - */ -public interface JcrMonitor { - /** - * Constant indicating an unknown amount of work. - */ - public final static int UNKNOWN = -1; - - /** - * Notifies that the main task is beginning. This must only be called once - * on a given progress monitor instance. - * - * @param name - * the name (or description) of the main task - * @param totalWork - * the total number of work units into which the main task is - * been subdivided. If the value is UNKNOWN the - * implementation is free to indicate progress in a way which - * doesn't require the total number of work units in advance. - */ - public void beginTask(String name, int totalWork); - - /** - * Notifies that the work is done; that is, either the main task is - * completed or the user canceled it. This method may be called more than - * once (implementations should be prepared to handle this case). - */ - public void done(); - - /** - * Returns whether cancelation of current operation has been requested. - * Long-running operations should poll to see if cancelation has been - * requested. - * - * @return true if cancellation has been requested, and - * false otherwise - * @see #setCanceled(boolean) - */ - public boolean isCanceled(); - - /** - * Sets the cancel state to the given value. - * - * @param value - * true indicates that cancelation has been - * requested (but not necessarily acknowledged); - * false clears this flag - * @see #isCanceled() - */ - public void setCanceled(boolean value); - - /** - * Sets the task name to the given value. This method is used to restore the - * task label after a nested operation was executed. Normally there is no - * need for clients to call this method. - * - * @param name - * the name (or description) of the main task - * @see #beginTask(java.lang.String, int) - */ - public void setTaskName(String name); - - /** - * Notifies that a subtask of the main task is beginning. Subtasks are - * optional; the main task might not have subtasks. - * - * @param name - * the name (or description) of the subtask - */ - public void subTask(String name); - - /** - * Notifies that a given number of work unit of the main task has been - * completed. Note that this amount represents an installment, as opposed to - * a cumulative amount of work done to date. - * - * @param work - * a non-negative number of work units just completed - */ - public void worked(int work); - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrRepositoryWrapper.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrRepositoryWrapper.java deleted file mode 100644 index 3228eee74..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrRepositoryWrapper.java +++ /dev/null @@ -1,244 +0,0 @@ -package org.argeo.jcr; - -import java.io.InputStream; -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Binary; -import javax.jcr.Credentials; -import javax.jcr.LoginException; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; - -/** - * Wrapper around a JCR repository which allows to simplify configuration and - * intercept some actions. It exposes itself as a {@link Repository}. - */ -public abstract class JcrRepositoryWrapper implements Repository { - // private final static Log log = LogFactory - // .getLog(JcrRepositoryWrapper.class); - - // wrapped repository - private Repository repository; - - private Map additionalDescriptors = new HashMap<>(); - - private Boolean autocreateWorkspaces = false; - - public JcrRepositoryWrapper(Repository repository) { - setRepository(repository); - } - - /** - * Empty constructor - */ - public JcrRepositoryWrapper() { - } - - // /** Initializes */ - // public void init() { - // } - // - // /** Shutdown the repository */ - // public void destroy() throws Exception { - // } - - protected void putDescriptor(String key, String value) { - if (Arrays.asList(getRepository().getDescriptorKeys()).contains(key)) - throw new IllegalArgumentException("Descriptor key " + key + " is already defined in wrapped repository"); - if (value == null) - additionalDescriptors.remove(key); - else - additionalDescriptors.put(key, value); - } - - /* - * DELEGATED JCR REPOSITORY METHODS - */ - - public String getDescriptor(String key) { - if (additionalDescriptors.containsKey(key)) - return additionalDescriptors.get(key); - return getRepository().getDescriptor(key); - } - - public String[] getDescriptorKeys() { - if (additionalDescriptors.size() == 0) - return getRepository().getDescriptorKeys(); - List keys = Arrays.asList(getRepository().getDescriptorKeys()); - keys.addAll(additionalDescriptors.keySet()); - return keys.toArray(new String[keys.size()]); - } - - /** Central login method */ - public Session login(Credentials credentials, String workspaceName) - throws LoginException, NoSuchWorkspaceException, RepositoryException { - Session session; - try { - session = getRepository(workspaceName).login(credentials, workspaceName); - } catch (NoSuchWorkspaceException e) { - if (autocreateWorkspaces && workspaceName != null) - session = createWorkspaceAndLogsIn(credentials, workspaceName); - else - throw e; - } - processNewSession(session, workspaceName); - return session; - } - - public Session login() throws LoginException, RepositoryException { - return login(null, null); - } - - public Session login(Credentials credentials) throws LoginException, RepositoryException { - return login(credentials, null); - } - - public Session login(String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException { - return login(null, workspaceName); - } - - /** Called after a session has been created, does nothing by default. */ - protected void processNewSession(Session session, String workspaceName) { - } - - /** - * Wraps access to the repository, making sure it is available. - * - * @deprecated Use {@link #getDefaultRepository()} instead. - */ - @Deprecated - protected synchronized Repository getRepository() { - return getDefaultRepository(); - } - - protected synchronized Repository getDefaultRepository() { - return repository; - } - - protected synchronized Repository getRepository(String workspaceName) { - return getDefaultRepository(); - } - - /** - * Logs in to the default workspace, creates the required workspace, logs out, - * logs in to the required workspace. - */ - protected Session createWorkspaceAndLogsIn(Credentials credentials, String workspaceName) - throws RepositoryException { - if (workspaceName == null) - throw new IllegalArgumentException("No workspace specified."); - Session session = getRepository(workspaceName).login(credentials); - session.getWorkspace().createWorkspace(workspaceName); - session.logout(); - return getRepository(workspaceName).login(credentials, workspaceName); - } - - public boolean isStandardDescriptor(String key) { - return getRepository().isStandardDescriptor(key); - } - - public boolean isSingleValueDescriptor(String key) { - if (additionalDescriptors.containsKey(key)) - return true; - return getRepository().isSingleValueDescriptor(key); - } - - public Value getDescriptorValue(String key) { - if (additionalDescriptors.containsKey(key)) - return new StrValue(additionalDescriptors.get(key)); - return getRepository().getDescriptorValue(key); - } - - public Value[] getDescriptorValues(String key) { - return getRepository().getDescriptorValues(key); - } - - public synchronized void setRepository(Repository repository) { - this.repository = repository; - } - - public void setAutocreateWorkspaces(Boolean autocreateWorkspaces) { - this.autocreateWorkspaces = autocreateWorkspaces; - } - - protected static class StrValue implements Value { - private final String str; - - public StrValue(String str) { - this.str = str; - } - - @Override - public String getString() throws ValueFormatException, IllegalStateException, RepositoryException { - return str; - } - - @Override - public InputStream getStream() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public Binary getBinary() throws RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public long getLong() throws ValueFormatException, RepositoryException { - try { - return Long.parseLong(str); - } catch (NumberFormatException e) { - throw new ValueFormatException("Cannot convert", e); - } - } - - @Override - public double getDouble() throws ValueFormatException, RepositoryException { - try { - return Double.parseDouble(str); - } catch (NumberFormatException e) { - throw new ValueFormatException("Cannot convert", e); - } - } - - @Override - public BigDecimal getDecimal() throws ValueFormatException, RepositoryException { - try { - return new BigDecimal(str); - } catch (NumberFormatException e) { - throw new ValueFormatException("Cannot convert", e); - } - } - - @Override - public Calendar getDate() throws ValueFormatException, RepositoryException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean() throws ValueFormatException, RepositoryException { - try { - return Boolean.parseBoolean(str); - } catch (NumberFormatException e) { - throw new ValueFormatException("Cannot convert", e); - } - } - - @Override - public int getType() { - return PropertyType.STRING; - } - - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUrlStreamHandler.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUrlStreamHandler.java deleted file mode 100644 index 82a65e7f1..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUrlStreamHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.argeo.jcr; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -/** URL stream handler able to deal with nt:file node and properties. NOT FINISHED */ -public class JcrUrlStreamHandler extends URLStreamHandler { - private final Session session; - - public JcrUrlStreamHandler(Session session) { - this.session = session; - } - - @Override - protected URLConnection openConnection(final URL u) throws IOException { - // TODO Auto-generated method stub - return new URLConnection(u) { - - @Override - public void connect() throws IOException { - String itemPath = u.getPath(); - try { - if (!session.itemExists(itemPath)) - throw new IOException("No item under " + itemPath); - - Item item = session.getItem(u.getPath()); - if (item.isNode()) { - // this should be a nt:file node - Node node = (Node) item; - if (!node.getPrimaryNodeType().isNodeType( - NodeType.NT_FILE)) - throw new IOException("Node " + node + " is not a " - + NodeType.NT_FILE); - - } else { - Property property = (Property) item; - if(property.getType()==PropertyType.BINARY){ - //Binary binary = property.getBinary(); - - } - } - } catch (RepositoryException e) { - IOException ioe = new IOException( - "Unexpected JCR exception"); - ioe.initCause(e); - throw ioe; - } - } - - @Override - public InputStream getInputStream() throws IOException { - // TODO Auto-generated method stub - return super.getInputStream(); - } - - }; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUtils.java deleted file mode 100644 index 1f1fa1121..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrUtils.java +++ /dev/null @@ -1,1786 +0,0 @@ -package org.argeo.jcr; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.text.DateFormat; -import java.text.ParseException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Binary; -import javax.jcr.Credentials; -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.NamespaceRegistry; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.Workspace; -import javax.jcr.nodetype.NoSuchNodeTypeException; -import javax.jcr.nodetype.NodeType; -import javax.jcr.observation.EventListener; -import javax.jcr.query.Query; -import javax.jcr.query.QueryResult; -import javax.jcr.security.AccessControlEntry; -import javax.jcr.security.AccessControlList; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.AccessControlPolicy; -import javax.jcr.security.AccessControlPolicyIterator; -import javax.jcr.security.Privilege; - -import org.apache.commons.io.IOUtils; - -/** Utility methods to simplify common JCR operations. */ -public class JcrUtils { - -// final private static Log log = LogFactory.getLog(JcrUtils.class); - - /** - * Not complete yet. See - * http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.2.2%20Local - * %20Names - */ - public final static char[] INVALID_NAME_CHARACTERS = { '/', ':', '[', ']', '|', '*', /* invalid for XML: */ '<', - '>', '&' }; - - /** Prevents instantiation */ - private JcrUtils() { - } - - /** - * Queries one single node. - * - * @return one single node or null if none was found - * @throws JcrException if more than one node was found - */ - public static Node querySingleNode(Query query) { - NodeIterator nodeIterator; - try { - QueryResult queryResult = query.execute(); - nodeIterator = queryResult.getNodes(); - } catch (RepositoryException e) { - throw new JcrException("Cannot execute query " + query, e); - } - Node node; - if (nodeIterator.hasNext()) - node = nodeIterator.nextNode(); - else - return null; - - if (nodeIterator.hasNext()) - throw new IllegalArgumentException("Query returned more than one node."); - return node; - } - - /** Retrieves the node name from the provided path */ - public static String nodeNameFromPath(String path) { - if (path.equals("/")) - return ""; - if (path.charAt(0) != '/') - throw new IllegalArgumentException("Path " + path + " must start with a '/'"); - String pathT = path; - if (pathT.charAt(pathT.length() - 1) == '/') - pathT = pathT.substring(0, pathT.length() - 2); - - int index = pathT.lastIndexOf('/'); - return pathT.substring(index + 1); - } - - /** Retrieves the parent path of the provided path */ - public static String parentPath(String path) { - if (path.equals("/")) - throw new IllegalArgumentException("Root path '/' has no parent path"); - if (path.charAt(0) != '/') - throw new IllegalArgumentException("Path " + path + " must start with a '/'"); - String pathT = path; - if (pathT.charAt(pathT.length() - 1) == '/') - pathT = pathT.substring(0, pathT.length() - 2); - - int index = pathT.lastIndexOf('/'); - return pathT.substring(0, index); - } - - /** The provided data as a path ('/' at the end, not the beginning) */ - public static String dateAsPath(Calendar cal) { - return dateAsPath(cal, false); - } - - /** - * Creates a deep path based on a URL: - * http://subdomain.example.com/to/content?args becomes - * com/example/subdomain/to/content - */ - public static String urlAsPath(String url) { - try { - URL u = new URL(url); - StringBuffer path = new StringBuffer(url.length()); - // invert host - path.append(hostAsPath(u.getHost())); - // we don't put port since it may not always be there and may change - path.append(u.getPath()); - return path.toString(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot generate URL path for " + url, e); - } - } - - /** Set the {@link NodeType#NT_ADDRESS} properties based on this URL. */ - public static void urlToAddressProperties(Node node, String url) { - try { - URL u = new URL(url); - node.setProperty(Property.JCR_PROTOCOL, u.getProtocol()); - node.setProperty(Property.JCR_HOST, u.getHost()); - node.setProperty(Property.JCR_PORT, Integer.toString(u.getPort())); - node.setProperty(Property.JCR_PATH, normalizePath(u.getPath())); - } catch (RepositoryException e) { - throw new JcrException("Cannot set URL " + url + " as nt:address properties", e); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot set URL " + url + " as nt:address properties", e); - } - } - - /** Build URL based on the {@link NodeType#NT_ADDRESS} properties. */ - public static String urlFromAddressProperties(Node node) { - try { - URL u = new URL(node.getProperty(Property.JCR_PROTOCOL).getString(), - node.getProperty(Property.JCR_HOST).getString(), - (int) node.getProperty(Property.JCR_PORT).getLong(), - node.getProperty(Property.JCR_PATH).getString()); - return u.toString(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get URL from nt:address properties of " + node, e); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Cannot get URL from nt:address properties of " + node, e); - } - } - - /* - * PATH UTILITIES - */ - - /** - * Make sure that: starts with '/', do not end with '/', do not have '//' - */ - public static String normalizePath(String path) { - List tokens = tokenize(path); - StringBuffer buf = new StringBuffer(path.length()); - for (String token : tokens) { - buf.append('/'); - buf.append(token); - } - return buf.toString(); - } - - /** - * Creates a path from a FQDN, inverting the order of the component: - * www.argeo.org becomes org.argeo.www - */ - public static String hostAsPath(String host) { - StringBuffer path = new StringBuffer(host.length()); - String[] hostTokens = host.split("\\."); - for (int i = hostTokens.length - 1; i >= 0; i--) { - path.append(hostTokens[i]); - if (i != 0) - path.append('/'); - } - return path.toString(); - } - - /** - * Creates a path from a UUID (e.g. 6ebda899-217d-4bf1-abe4-2839085c8f3c becomes - * 6ebda899-217d/4bf1/abe4/2839085c8f3c/). '/' at the end, not the beginning - */ - public static String uuidAsPath(String uuid) { - StringBuffer path = new StringBuffer(uuid.length()); - String[] tokens = uuid.split("-"); - for (int i = 0; i < tokens.length; i++) { - path.append(tokens[i]); - if (i != 0) - path.append('/'); - } - return path.toString(); - } - - /** - * The provided data as a path ('/' at the end, not the beginning) - * - * @param cal the date - * @param addHour whether to add hour as well - */ - public static String dateAsPath(Calendar cal, Boolean addHour) { - StringBuffer buf = new StringBuffer(14); - buf.append('Y'); - buf.append(cal.get(Calendar.YEAR)); - buf.append('/'); - - int month = cal.get(Calendar.MONTH) + 1; - buf.append('M'); - if (month < 10) - buf.append(0); - buf.append(month); - buf.append('/'); - - int day = cal.get(Calendar.DAY_OF_MONTH); - buf.append('D'); - if (day < 10) - buf.append(0); - buf.append(day); - buf.append('/'); - - if (addHour) { - int hour = cal.get(Calendar.HOUR_OF_DAY); - buf.append('H'); - if (hour < 10) - buf.append(0); - buf.append(hour); - buf.append('/'); - } - return buf.toString(); - - } - - /** Converts in one call a string into a gregorian calendar. */ - public static Calendar parseCalendar(DateFormat dateFormat, String value) { - try { - Date date = dateFormat.parse(value); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(date); - return calendar; - } catch (ParseException e) { - throw new IllegalArgumentException("Cannot parse " + value + " with date format " + dateFormat, e); - } - - } - - /** The last element of a path. */ - public static String lastPathElement(String path) { - if (path.charAt(path.length() - 1) == '/') - throw new IllegalArgumentException("Path " + path + " cannot end with '/'"); - int index = path.lastIndexOf('/'); - if (index < 0) - return path; - return path.substring(index + 1); - } - - /** - * Call {@link Node#getName()} without exceptions (useful in super - * constructors). - */ - public static String getNameQuietly(Node node) { - try { - return node.getName(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get name from " + node, e); - } - } - - /** - * Call {@link Node#getProperty(String)} without exceptions (useful in super - * constructors). - */ - public static String getStringPropertyQuietly(Node node, String propertyName) { - try { - return node.getProperty(propertyName).getString(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get name from " + node, e); - } - } - -// /** -// * Routine that get the child with this name, adding it if it does not already -// * exist -// */ -// public static Node getOrAdd(Node parent, String name, String primaryNodeType) throws RepositoryException { -// return parent.hasNode(name) ? parent.getNode(name) : parent.addNode(name, primaryNodeType); -// } - - /** - * Routine that get the child with this name, adding it if it does not already - * exist - */ - public static Node getOrAdd(Node parent, String name, String primaryNodeType, String... mixinNodeTypes) - throws RepositoryException { - Node node; - if (parent.hasNode(name)) { - node = parent.getNode(name); - if (primaryNodeType != null && !node.isNodeType(primaryNodeType)) - throw new IllegalArgumentException("Node " + node + " exists but is of primary node type " - + node.getPrimaryNodeType().getName() + ", not " + primaryNodeType); - for (String mixin : mixinNodeTypes) { - if (!node.isNodeType(mixin)) - node.addMixin(mixin); - } - return node; - } else { - node = primaryNodeType != null ? parent.addNode(name, primaryNodeType) : parent.addNode(name); - for (String mixin : mixinNodeTypes) { - node.addMixin(mixin); - } - return node; - } - } - - /** - * Routine that get the child with this name, adding it if it does not already - * exist - */ - public static Node getOrAdd(Node parent, String name) throws RepositoryException { - return parent.hasNode(name) ? parent.getNode(name) : parent.addNode(name); - } - - /** Convert a {@link NodeIterator} to a list of {@link Node} */ - public static List nodeIteratorToList(NodeIterator nodeIterator) { - List nodes = new ArrayList(); - while (nodeIterator.hasNext()) { - nodes.add(nodeIterator.nextNode()); - } - return nodes; - } - - /* - * PROPERTIES - */ - - /** - * Concisely get the string value of a property or null if this node doesn't - * have this property - */ - public static String get(Node node, String propertyName) { - try { - if (!node.hasProperty(propertyName)) - return null; - return node.getProperty(propertyName).getString(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property " + propertyName + " of " + node, e); - } - } - - /** Concisely get the path of the given node. */ - public static String getPath(Node node) { - try { - return node.getPath(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get path of " + node, e); - } - } - - /** Concisely get the boolean value of a property */ - public static Boolean check(Node node, String propertyName) { - try { - return node.getProperty(propertyName).getBoolean(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property " + propertyName + " of " + node, e); - } - } - - /** Concisely get the bytes array value of a property */ - public static byte[] getBytes(Node node, String propertyName) { - try { - return getBinaryAsBytes(node.getProperty(propertyName)); - } catch (RepositoryException e) { - throw new JcrException("Cannot get property " + propertyName + " of " + node, e); - } - } - - /* - * MKDIRS - */ - - /** - * Create sub nodes relative to a parent node - */ - public static Node mkdirs(Node parentNode, String relativePath) { - return mkdirs(parentNode, relativePath, null, null); - } - - /** - * Create sub nodes relative to a parent node - * - * @param nodeType the type of the leaf node - */ - public static Node mkdirs(Node parentNode, String relativePath, String nodeType) { - return mkdirs(parentNode, relativePath, nodeType, null); - } - - /** - * Create sub nodes relative to a parent node - * - * @param nodeType the type of the leaf node - */ - public static Node mkdirs(Node parentNode, String relativePath, String nodeType, String intermediaryNodeType) { - List tokens = tokenize(relativePath); - Node currParent = parentNode; - try { - for (int i = 0; i < tokens.size(); i++) { - String name = tokens.get(i); - if (currParent.hasNode(name)) { - currParent = currParent.getNode(name); - } else { - if (i != (tokens.size() - 1)) {// intermediary - currParent = currParent.addNode(name, intermediaryNodeType); - } else {// leaf - currParent = currParent.addNode(name, nodeType); - } - } - } - return currParent; - } catch (RepositoryException e) { - throw new JcrException("Cannot mkdirs relative path " + relativePath + " from " + parentNode, e); - } - } - - /** - * Synchronized and save is performed, to avoid race conditions in initializers - * leading to duplicate nodes. - */ - public synchronized static Node mkdirsSafe(Session session, String path, String type) { - try { - if (session.hasPendingChanges()) - throw new IllegalStateException("Session has pending changes, save them first."); - Node node = mkdirs(session, path, type); - session.save(); - return node; - } catch (RepositoryException e) { - discardQuietly(session); - throw new JcrException("Cannot safely make directories", e); - } - } - - public synchronized static Node mkdirsSafe(Session session, String path) { - return mkdirsSafe(session, path, null); - } - - /** Creates the nodes making path, if they don't exist. */ - public static Node mkdirs(Session session, String path) { - return mkdirs(session, path, null, null, false); - } - - /** - * @param type the type of the leaf node - */ - public static Node mkdirs(Session session, String path, String type) { - return mkdirs(session, path, type, null, false); - } - - /** - * Creates the nodes making path, if they don't exist. This is up to the caller - * to save the session. Use with caution since it can create duplicate nodes if - * used concurrently. Requires read access to the root node of the workspace. - */ - public static Node mkdirs(Session session, String path, String type, String intermediaryNodeType, - Boolean versioning) { - try { - if (path.equals("/")) - return session.getRootNode(); - - if (session.itemExists(path)) { - Node node = session.getNode(path); - // check type - if (type != null && !node.isNodeType(type) && !node.getPath().equals("/")) - throw new IllegalArgumentException("Node " + node + " exists but is of type " - + node.getPrimaryNodeType().getName() + " not of type " + type); - // TODO: check versioning - return node; - } - - // StringBuffer current = new StringBuffer("/"); - // Node currentNode = session.getRootNode(); - - Node currentNode = findClosestExistingParent(session, path); - String closestExistingParentPath = currentNode.getPath(); - StringBuffer current = new StringBuffer(closestExistingParentPath); - if (!closestExistingParentPath.endsWith("/")) - current.append('/'); - Iterator it = tokenize(path.substring(closestExistingParentPath.length())).iterator(); - while (it.hasNext()) { - String part = it.next(); - current.append(part).append('/'); - if (!session.itemExists(current.toString())) { - if (!it.hasNext() && type != null) - currentNode = currentNode.addNode(part, type); - else if (it.hasNext() && intermediaryNodeType != null) - currentNode = currentNode.addNode(part, intermediaryNodeType); - else - currentNode = currentNode.addNode(part); - if (versioning) - currentNode.addMixin(NodeType.MIX_VERSIONABLE); -// if (log.isTraceEnabled()) -// log.debug("Added folder " + part + " as " + current); - } else { - currentNode = (Node) session.getItem(current.toString()); - } - } - return currentNode; - } catch (RepositoryException e) { - discardQuietly(session); - throw new JcrException("Cannot mkdirs " + path, e); - } finally { - } - } - - private static Node findClosestExistingParent(Session session, String path) throws RepositoryException { - int idx = path.lastIndexOf('/'); - if (idx == 0) - return session.getRootNode(); - String parentPath = path.substring(0, idx); - if (session.itemExists(parentPath)) - return session.getNode(parentPath); - else - return findClosestExistingParent(session, parentPath); - } - - /** Convert a path to the list of its tokens */ - public static List tokenize(String path) { - List tokens = new ArrayList(); - boolean optimized = false; - if (!optimized) { - String[] rawTokens = path.split("/"); - for (String token : rawTokens) { - if (!token.equals("")) - tokens.add(token); - } - } else { - StringBuffer curr = new StringBuffer(); - char[] arr = path.toCharArray(); - chars: for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - if (c == '/') { - if (i == 0 || (i == arr.length - 1)) - continue chars; - if (curr.length() > 0) { - tokens.add(curr.toString()); - curr = new StringBuffer(); - } - } else - curr.append(c); - } - if (curr.length() > 0) { - tokens.add(curr.toString()); - curr = new StringBuffer(); - } - } - return Collections.unmodifiableList(tokens); - } - - // /** - // * use {@link #mkdirs(Session, String, String, String, Boolean)} instead. - // * - // * @deprecated - // */ - // @Deprecated - // public static Node mkdirs(Session session, String path, String type, - // Boolean versioning) { - // return mkdirs(session, path, type, type, false); - // } - - /** - * Safe and repository implementation independent registration of a namespace. - */ - public static void registerNamespaceSafely(Session session, String prefix, String uri) { - try { - registerNamespaceSafely(session.getWorkspace().getNamespaceRegistry(), prefix, uri); - } catch (RepositoryException e) { - throw new JcrException("Cannot find namespace registry", e); - } - } - - /** - * Safe and repository implementation independent registration of a namespace. - */ - public static void registerNamespaceSafely(NamespaceRegistry nr, String prefix, String uri) { - try { - String[] prefixes = nr.getPrefixes(); - for (String pref : prefixes) - if (pref.equals(prefix)) { - String registeredUri = nr.getURI(pref); - if (!registeredUri.equals(uri)) - throw new IllegalArgumentException("Prefix " + pref + " already registered for URI " - + registeredUri + " which is different from provided URI " + uri); - else - return;// skip - } - nr.registerNamespace(prefix, uri); - } catch (RepositoryException e) { - throw new JcrException("Cannot register namespace " + uri + " under prefix " + prefix, e); - } - } - -// /** Recursively outputs the contents of the given node. */ -// public static void debug(Node node) { -// debug(node, log); -// } -// -// /** Recursively outputs the contents of the given node. */ -// public static void debug(Node node, Log log) { -// try { -// // First output the node path -// log.debug(node.getPath()); -// // Skip the virtual (and large!) jcr:system subtree -// if (node.getName().equals("jcr:system")) { -// return; -// } -// -// // Then the children nodes (recursive) -// NodeIterator it = node.getNodes(); -// while (it.hasNext()) { -// Node childNode = it.nextNode(); -// debug(childNode, log); -// } -// -// // Then output the properties -// PropertyIterator properties = node.getProperties(); -// // log.debug("Property are : "); -// -// properties: while (properties.hasNext()) { -// Property property = properties.nextProperty(); -// if (property.getType() == PropertyType.BINARY) -// continue properties;// skip -// if (property.getDefinition().isMultiple()) { -// // A multi-valued property, print all values -// Value[] values = property.getValues(); -// for (int i = 0; i < values.length; i++) { -// log.debug(property.getPath() + "=" + values[i].getString()); -// } -// } else { -// // A single-valued property -// log.debug(property.getPath() + "=" + property.getString()); -// } -// } -// } catch (Exception e) { -// log.error("Could not debug " + node, e); -// } -// -// } - -// /** Logs the effective access control policies */ -// public static void logEffectiveAccessPolicies(Node node) { -// try { -// logEffectiveAccessPolicies(node.getSession(), node.getPath()); -// } catch (RepositoryException e) { -// log.error("Cannot log effective access policies of " + node, e); -// } -// } -// -// /** Logs the effective access control policies */ -// public static void logEffectiveAccessPolicies(Session session, String path) { -// if (!log.isDebugEnabled()) -// return; -// -// try { -// AccessControlPolicy[] effectivePolicies = session.getAccessControlManager().getEffectivePolicies(path); -// if (effectivePolicies.length > 0) { -// for (AccessControlPolicy policy : effectivePolicies) { -// if (policy instanceof AccessControlList) { -// AccessControlList acl = (AccessControlList) policy; -// log.debug("Access control list for " + path + "\n" + accessControlListSummary(acl)); -// } -// } -// } else { -// log.debug("No effective access control policy for " + path); -// } -// } catch (RepositoryException e) { -// log.error("Cannot log effective access policies of " + path, e); -// } -// } - - /** Returns a human-readable summary of this access control list. */ - public static String accessControlListSummary(AccessControlList acl) { - StringBuffer buf = new StringBuffer(""); - try { - for (AccessControlEntry ace : acl.getAccessControlEntries()) { - buf.append('\t').append(ace.getPrincipal().getName()).append('\n'); - for (Privilege priv : ace.getPrivileges()) - buf.append("\t\t").append(priv.getName()).append('\n'); - } - return buf.toString(); - } catch (RepositoryException e) { - throw new JcrException("Cannot write summary of " + acl, e); - } - } - - /** Copy the whole workspace via a system view XML. */ - public static void copyWorkspaceXml(Session fromSession, Session toSession) { - Workspace fromWorkspace = fromSession.getWorkspace(); - Workspace toWorkspace = toSession.getWorkspace(); - String errorMsg = "Cannot copy workspace " + fromWorkspace + " to " + toWorkspace + " via XML."; - - try (PipedInputStream in = new PipedInputStream(1024 * 1024);) { - new Thread(() -> { - try (PipedOutputStream out = new PipedOutputStream(in)) { - fromSession.exportSystemView("/", out, false, false); - out.flush(); - } catch (IOException e) { - throw new RuntimeException(errorMsg, e); - } catch (RepositoryException e) { - throw new JcrException(errorMsg, e); - } - }, "Copy workspace" + fromWorkspace + " to " + toWorkspace).start(); - - toSession.importXML("/", in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); - toSession.save(); - } catch (IOException e) { - throw new RuntimeException(errorMsg, e); - } catch (RepositoryException e) { - throw new JcrException(errorMsg, e); - } - } - - /** - * Copies recursively the content of a node to another one. Do NOT copy the - * property values of {@link NodeType#MIX_CREATED} and - * {@link NodeType#MIX_LAST_MODIFIED}, but update the - * {@link Property#JCR_LAST_MODIFIED} and {@link Property#JCR_LAST_MODIFIED_BY} - * properties if the target node has the {@link NodeType#MIX_LAST_MODIFIED} - * mixin. - */ - public static void copy(Node fromNode, Node toNode) { - try { - if (toNode.getDefinition().isProtected()) - return; - - // add mixins - for (NodeType mixinType : fromNode.getMixinNodeTypes()) { - try { - toNode.addMixin(mixinType.getName()); - } catch (NoSuchNodeTypeException e) { - // ignore unknown mixins - // TODO log it - } - } - - // process properties - PropertyIterator pit = fromNode.getProperties(); - properties: while (pit.hasNext()) { - Property fromProperty = pit.nextProperty(); - String propertyName = fromProperty.getName(); - if (toNode.hasProperty(propertyName) && toNode.getProperty(propertyName).getDefinition().isProtected()) - continue properties; - - if (fromProperty.getDefinition().isProtected()) - continue properties; - - if (propertyName.equals("jcr:created") || propertyName.equals("jcr:createdBy") - || propertyName.equals("jcr:lastModified") || propertyName.equals("jcr:lastModifiedBy")) - continue properties; - - if (fromProperty.isMultiple()) { - toNode.setProperty(propertyName, fromProperty.getValues()); - } else { - toNode.setProperty(propertyName, fromProperty.getValue()); - } - } - - // update jcr:lastModified and jcr:lastModifiedBy in toNode in case - // they existed, before adding the mixins - updateLastModified(toNode, true); - - // process children nodes - NodeIterator nit = fromNode.getNodes(); - while (nit.hasNext()) { - Node fromChild = nit.nextNode(); - Integer index = fromChild.getIndex(); - String nodeRelPath = fromChild.getName() + "[" + index + "]"; - Node toChild; - if (toNode.hasNode(nodeRelPath)) - toChild = toNode.getNode(nodeRelPath); - else { - try { - toChild = toNode.addNode(fromChild.getName(), fromChild.getPrimaryNodeType().getName()); - } catch (NoSuchNodeTypeException e) { - // ignore unknown primary types - // TODO log it - return; - } - } - copy(fromChild, toChild); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot copy " + fromNode + " to " + toNode, e); - } - } - - /** - * Check whether all first-level properties (except jcr:* properties) are equal. - * Skip jcr:* properties - */ - public static Boolean allPropertiesEquals(Node reference, Node observed, Boolean onlyCommonProperties) { - try { - PropertyIterator pit = reference.getProperties(); - props: while (pit.hasNext()) { - Property propReference = pit.nextProperty(); - String propName = propReference.getName(); - if (propName.startsWith("jcr:")) - continue props; - - if (!observed.hasProperty(propName)) - if (onlyCommonProperties) - continue props; - else - return false; - // TODO: deal with multiple property values? - if (!observed.getProperty(propName).getValue().equals(propReference.getValue())) - return false; - } - return true; - } catch (RepositoryException e) { - throw new JcrException("Cannot check all properties equals of " + reference + " and " + observed, e); - } - } - - public static Map diffProperties(Node reference, Node observed) { - Map diffs = new TreeMap(); - diffPropertiesLevel(diffs, null, reference, observed); - return diffs; - } - - /** - * Compare the properties of two nodes. Recursivity to child nodes is not yet - * supported. Skip jcr:* properties. - */ - static void diffPropertiesLevel(Map diffs, String baseRelPath, Node reference, - Node observed) { - try { - // check removed and modified - PropertyIterator pit = reference.getProperties(); - props: while (pit.hasNext()) { - Property p = pit.nextProperty(); - String name = p.getName(); - if (name.startsWith("jcr:")) - continue props; - - if (!observed.hasProperty(name)) { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, relPath, p.getValue(), null); - diffs.put(relPath, pDiff); - } else { - if (p.isMultiple()) { - // FIXME implement multiple - } else { - Value referenceValue = p.getValue(); - Value newValue = observed.getProperty(name).getValue(); - if (!referenceValue.equals(newValue)) { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.MODIFIED, relPath, referenceValue, - newValue); - diffs.put(relPath, pDiff); - } - } - } - } - // check added - pit = observed.getProperties(); - props: while (pit.hasNext()) { - Property p = pit.nextProperty(); - String name = p.getName(); - if (name.startsWith("jcr:")) - continue props; - if (!reference.hasProperty(name)) { - if (p.isMultiple()) { - // FIXME implement multiple - } else { - String relPath = propertyRelPath(baseRelPath, name); - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, relPath, null, p.getValue()); - diffs.put(relPath, pDiff); - } - } - } - } catch (RepositoryException e) { - throw new JcrException("Cannot diff " + reference + " and " + observed, e); - } - } - - /** - * Compare only a restricted list of properties of two nodes. No recursivity. - * - */ - public static Map diffProperties(Node reference, Node observed, List properties) { - Map diffs = new TreeMap(); - try { - Iterator pit = properties.iterator(); - - props: while (pit.hasNext()) { - String name = pit.next(); - if (!reference.hasProperty(name)) { - if (!observed.hasProperty(name)) - continue props; - Value val = observed.getProperty(name).getValue(); - try { - // empty String but not null - if ("".equals(val.getString())) - continue props; - } catch (Exception e) { - // not parseable as String, silent - } - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, name, null, val); - diffs.put(name, pDiff); - } else if (!observed.hasProperty(name)) { - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, name, - reference.getProperty(name).getValue(), null); - diffs.put(name, pDiff); - } else { - Value referenceValue = reference.getProperty(name).getValue(); - Value newValue = observed.getProperty(name).getValue(); - if (!referenceValue.equals(newValue)) { - PropertyDiff pDiff = new PropertyDiff(PropertyDiff.MODIFIED, name, referenceValue, newValue); - diffs.put(name, pDiff); - } - } - } - } catch (RepositoryException e) { - throw new JcrException("Cannot diff " + reference + " and " + observed, e); - } - return diffs; - } - - /** Builds a property relPath to be used in the diff. */ - private static String propertyRelPath(String baseRelPath, String propertyName) { - if (baseRelPath == null) - return propertyName; - else - return baseRelPath + '/' + propertyName; - } - - /** - * Normalizes a name so that it can be stored in contexts not supporting names - * with ':' (typically databases). Replaces ':' by '_'. - */ - public static String normalize(String name) { - return name.replace(':', '_'); - } - - /** - * Replaces characters which are invalid in a JCR name by '_'. Currently not - * exhaustive. - * - * @see JcrUtils#INVALID_NAME_CHARACTERS - */ - public static String replaceInvalidChars(String name) { - return replaceInvalidChars(name, '_'); - } - - /** - * Replaces characters which are invalid in a JCR name. Currently not - * exhaustive. - * - * @see JcrUtils#INVALID_NAME_CHARACTERS - */ - public static String replaceInvalidChars(String name, char replacement) { - boolean modified = false; - char[] arr = name.toCharArray(); - for (int i = 0; i < arr.length; i++) { - char c = arr[i]; - invalid: for (char invalid : INVALID_NAME_CHARACTERS) { - if (c == invalid) { - arr[i] = replacement; - modified = true; - break invalid; - } - } - } - if (modified) - return new String(arr); - else - // do not create new object if unnecessary - return name; - } - - // /** - // * Removes forbidden characters from a path, replacing them with '_' - // * - // * @deprecated use {@link #replaceInvalidChars(String)} instead - // */ - // public static String removeForbiddenCharacters(String str) { - // return str.replace('[', '_').replace(']', '_').replace('/', '_').replace('*', - // '_'); - // - // } - - /** Cleanly disposes a {@link Binary} even if it is null. */ - public static void closeQuietly(Binary binary) { - if (binary == null) - return; - binary.dispose(); - } - - /** Retrieve a {@link Binary} as a byte array */ - public static byte[] getBinaryAsBytes(Property property) { - try (ByteArrayOutputStream out = new ByteArrayOutputStream(); - Bin binary = new Bin(property); - InputStream in = binary.getStream()) { - IOUtils.copy(in, out); - return out.toByteArray(); - } catch (RepositoryException e) { - throw new JcrException("Cannot read binary " + property + " as bytes", e); - } catch (IOException e) { - throw new RuntimeException("Cannot read binary " + property + " as bytes", e); - } - } - - /** Writes a {@link Binary} from a byte array */ - public static void setBinaryAsBytes(Node node, String property, byte[] bytes) { - Binary binary = null; - try (InputStream in = new ByteArrayInputStream(bytes)) { - binary = node.getSession().getValueFactory().createBinary(in); - node.setProperty(property, binary); - } catch (RepositoryException e) { - throw new JcrException("Cannot set binary " + property + " as bytes", e); - } catch (IOException e) { - throw new RuntimeException("Cannot set binary " + property + " as bytes", e); - } finally { - closeQuietly(binary); - } - } - - /** Writes a {@link Binary} from a byte array */ - public static void setBinaryAsBytes(Property prop, byte[] bytes) { - Binary binary = null; - try (InputStream in = new ByteArrayInputStream(bytes)) { - binary = prop.getSession().getValueFactory().createBinary(in); - prop.setValue(binary); - } catch (RepositoryException e) { - throw new JcrException("Cannot set binary " + prop + " as bytes", e); - } catch (IOException e) { - throw new RuntimeException("Cannot set binary " + prop + " as bytes", e); - } finally { - closeQuietly(binary); - } - } - - /** - * Creates depth from a string (typically a username) by adding levels based on - * its first characters: "aBcD",2 becomes a/aB - */ - public static String firstCharsToPath(String str, Integer nbrOfChars) { - if (str.length() < nbrOfChars) - throw new IllegalArgumentException("String " + str + " length must be greater or equal than " + nbrOfChars); - StringBuffer path = new StringBuffer(""); - StringBuffer curr = new StringBuffer(""); - for (int i = 0; i < nbrOfChars; i++) { - curr.append(str.charAt(i)); - path.append(curr); - if (i < nbrOfChars - 1) - path.append('/'); - } - return path.toString(); - } - - /** - * Discards the current changes in the session attached to this node. To be used - * typically in a catch block. - * - * @see #discardQuietly(Session) - */ - public static void discardUnderlyingSessionQuietly(Node node) { - try { - discardQuietly(node.getSession()); - } catch (RepositoryException e) { - // silent - } - } - - /** - * Discards the current changes in a session by calling - * {@link Session#refresh(boolean)} with false, only logging - * potential errors when doing so. To be used typically in a catch block. - */ - public static void discardQuietly(Session session) { - try { - if (session != null) - session.refresh(false); - } catch (RepositoryException e) { - // silent - } - } - - /** - * Login to a workspace with implicit credentials, creates the workspace with - * these credentials if it does not already exist. - */ - public static Session loginOrCreateWorkspace(Repository repository, String workspaceName) - throws RepositoryException { - return loginOrCreateWorkspace(repository, workspaceName, null); - } - - /** - * Login to a workspace with implicit credentials, creates the workspace with - * these credentials if it does not already exist. - */ - public static Session loginOrCreateWorkspace(Repository repository, String workspaceName, Credentials credentials) - throws RepositoryException { - Session workspaceSession = null; - Session defaultSession = null; - try { - try { - workspaceSession = repository.login(credentials, workspaceName); - } catch (NoSuchWorkspaceException e) { - // try to create workspace - defaultSession = repository.login(credentials); - defaultSession.getWorkspace().createWorkspace(workspaceName); - - // work around non-atomicity of workspace creation in Jackrabbit -// try { -// Thread.sleep(5000); -// } catch (InterruptedException e1) { -// // ignore -// } - - workspaceSession = repository.login(credentials, workspaceName); - } - return workspaceSession; - } finally { - logoutQuietly(defaultSession); - } - } - - /** - * Logs out the session, not throwing any exception, even if it is null. - * {@link Jcr#logout(Session)} should rather be used. - */ - public static void logoutQuietly(Session session) { - Jcr.logout(session); -// try { -// if (session != null) -// if (session.isLive()) -// session.logout(); -// } catch (Exception e) { -// // silent -// } - } - - /** - * Convenient method to add a listener. uuids passed as null, deep=true, - * local=true, only one node type - */ - public static void addListener(Session session, EventListener listener, int eventTypes, String basePath, - String nodeType) { - try { - session.getWorkspace().getObservationManager().addEventListener(listener, eventTypes, basePath, true, null, - nodeType == null ? null : new String[] { nodeType }, true); - } catch (RepositoryException e) { - throw new JcrException("Cannot add JCR listener " + listener + " to session " + session, e); - } - } - - /** Removes a listener without throwing exception */ - public static void removeListenerQuietly(Session session, EventListener listener) { - if (session == null || !session.isLive()) - return; - try { - session.getWorkspace().getObservationManager().removeEventListener(listener); - } catch (RepositoryException e) { - // silent - } - } - - /** - * Quietly unregisters an {@link EventListener} from the udnerlying workspace of - * this node. - */ - public static void unregisterQuietly(Node node, EventListener eventListener) { - try { - unregisterQuietly(node.getSession().getWorkspace(), eventListener); - } catch (RepositoryException e) { - // silent - } - } - - /** Quietly unregisters an {@link EventListener} from this workspace */ - public static void unregisterQuietly(Workspace workspace, EventListener eventListener) { - if (eventListener == null) - return; - try { - workspace.getObservationManager().removeEventListener(eventListener); - } catch (RepositoryException e) { - // silent - } - } - - /** - * Checks whether {@link Property#JCR_LAST_MODIFIED} or (afterwards) - * {@link Property#JCR_CREATED} are set and returns it as an {@link Instant}. - */ - public static Instant getModified(Node node) { - Calendar calendar = null; - try { - if (node.hasProperty(Property.JCR_LAST_MODIFIED)) - calendar = node.getProperty(Property.JCR_LAST_MODIFIED).getDate(); - else if (node.hasProperty(Property.JCR_CREATED)) - calendar = node.getProperty(Property.JCR_CREATED).getDate(); - else - throw new IllegalArgumentException("No modification time found in " + node); - return calendar.toInstant(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get modification time for " + node, e); - } - - } - - /** - * Get {@link Property#JCR_CREATED} as an {@link Instant}, if it is set. - */ - public static Instant getCreated(Node node) { - Calendar calendar = null; - try { - if (node.hasProperty(Property.JCR_CREATED)) - calendar = node.getProperty(Property.JCR_CREATED).getDate(); - else - throw new IllegalArgumentException("No created time found in " + node); - return calendar.toInstant(); - } catch (RepositoryException e) { - throw new JcrException("Cannot get created time for " + node, e); - } - - } - - /** - * Updates the {@link Property#JCR_LAST_MODIFIED} property with the current time - * and the {@link Property#JCR_LAST_MODIFIED_BY} property with the underlying - * session user id. - */ - public static void updateLastModified(Node node) { - updateLastModified(node, false); - } - - /** - * Updates the {@link Property#JCR_LAST_MODIFIED} property with the current time - * and the {@link Property#JCR_LAST_MODIFIED_BY} property with the underlying - * session user id. In Jackrabbit 2.x, - * these properties are - * not automatically updated, hence the need for manual update. The session - * is not saved. - */ - public static void updateLastModified(Node node, boolean addMixin) { - try { - if (addMixin && !node.isNodeType(NodeType.MIX_LAST_MODIFIED)) - node.addMixin(NodeType.MIX_LAST_MODIFIED); - node.setProperty(Property.JCR_LAST_MODIFIED, new GregorianCalendar()); - node.setProperty(Property.JCR_LAST_MODIFIED_BY, node.getSession().getUserID()); - } catch (RepositoryException e) { - throw new JcrException("Cannot update last modified on " + node, e); - } - } - - /** - * Update lastModified recursively until this parent. - * - * @param node the node - * @param untilPath the base path, null is equivalent to "/" - */ - public static void updateLastModifiedAndParents(Node node, String untilPath) { - updateLastModifiedAndParents(node, untilPath, true); - } - - /** - * Update lastModified recursively until this parent. - * - * @param node the node - * @param untilPath the base path, null is equivalent to "/" - */ - public static void updateLastModifiedAndParents(Node node, String untilPath, boolean addMixin) { - try { - if (untilPath != null && !node.getPath().startsWith(untilPath)) - throw new IllegalArgumentException(node + " is not under " + untilPath); - updateLastModified(node, addMixin); - if (untilPath == null) { - if (!node.getPath().equals("/")) - updateLastModifiedAndParents(node.getParent(), untilPath, addMixin); - } else { - if (!node.getPath().equals(untilPath)) - updateLastModifiedAndParents(node.getParent(), untilPath, addMixin); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot update lastModified from " + node + " until " + untilPath, e); - } - } - - /** - * Returns a String representing the short version (see - * Node type - * Notation attributes grammar) of the main business attributes of this - * property definition - * - * @param prop - */ - public static String getPropertyDefinitionAsString(Property prop) { - StringBuffer sbuf = new StringBuffer(); - try { - if (prop.getDefinition().isAutoCreated()) - sbuf.append("a"); - if (prop.getDefinition().isMandatory()) - sbuf.append("m"); - if (prop.getDefinition().isProtected()) - sbuf.append("p"); - if (prop.getDefinition().isMultiple()) - sbuf.append("*"); - } catch (RepositoryException re) { - throw new JcrException("unexpected error while getting property definition as String", re); - } - return sbuf.toString(); - } - - /** - * Estimate the sub tree size from current node. Computation is based on the Jcr - * {@link Property#getLength()} method. Note : it is not the exact size used on - * the disk by the current part of the JCR Tree. - */ - - public static long getNodeApproxSize(Node node) { - long curNodeSize = 0; - try { - PropertyIterator pi = node.getProperties(); - while (pi.hasNext()) { - Property prop = pi.nextProperty(); - if (prop.isMultiple()) { - int nb = prop.getLengths().length; - for (int i = 0; i < nb; i++) { - curNodeSize += (prop.getLengths()[i] > 0 ? prop.getLengths()[i] : 0); - } - } else - curNodeSize += (prop.getLength() > 0 ? prop.getLength() : 0); - } - - NodeIterator ni = node.getNodes(); - while (ni.hasNext()) - curNodeSize += getNodeApproxSize(ni.nextNode()); - return curNodeSize; - } catch (RepositoryException re) { - throw new JcrException("Unexpected error while recursively determining node size.", re); - } - } - - /* - * SECURITY - */ - - /** - * Convenience method for adding a single privilege to a principal (user or - * role), typically jcr:all - */ - public synchronized static void addPrivilege(Session session, String path, String principal, String privilege) - throws RepositoryException { - List privileges = new ArrayList(); - privileges.add(session.getAccessControlManager().privilegeFromName(privilege)); - addPrivileges(session, path, new SimplePrincipal(principal), privileges); - } - - /** - * Add privileges on a path to a {@link Principal}. The path must already exist. - * Session is saved. Synchronized to prevent concurrent modifications of the - * same node. - */ - public synchronized static Boolean addPrivileges(Session session, String path, Principal principal, - List privs) throws RepositoryException { - // make sure the session is in line with the persisted state - session.refresh(false); - AccessControlManager acm = session.getAccessControlManager(); - AccessControlList acl = getAccessControlList(acm, path); - - accessControlEntries: for (AccessControlEntry ace : acl.getAccessControlEntries()) { - Principal currentPrincipal = ace.getPrincipal(); - if (currentPrincipal.getName().equals(principal.getName())) { - Privilege[] currentPrivileges = ace.getPrivileges(); - if (currentPrivileges.length != privs.size()) - break accessControlEntries; - for (int i = 0; i < currentPrivileges.length; i++) { - Privilege currP = currentPrivileges[i]; - Privilege p = privs.get(i); - if (!currP.getName().equals(p.getName())) { - break accessControlEntries; - } - } - return false; - } - } - - Privilege[] privileges = privs.toArray(new Privilege[privs.size()]); - acl.addAccessControlEntry(principal, privileges); - acm.setPolicy(path, acl); -// if (log.isDebugEnabled()) { -// StringBuffer privBuf = new StringBuffer(); -// for (Privilege priv : privs) -// privBuf.append(priv.getName()); -// log.debug("Added privileges " + privBuf + " to " + principal.getName() + " on " + path + " in '" -// + session.getWorkspace().getName() + "'"); -// } - session.refresh(true); - session.save(); - return true; - } - - /** - * Gets the first available access control list for this path, throws exception - * if not found - */ - public synchronized static AccessControlList getAccessControlList(AccessControlManager acm, String path) - throws RepositoryException { - // search for an access control list - AccessControlList acl = null; - AccessControlPolicyIterator policyIterator = acm.getApplicablePolicies(path); - applicablePolicies: if (policyIterator.hasNext()) { - while (policyIterator.hasNext()) { - AccessControlPolicy acp = policyIterator.nextAccessControlPolicy(); - if (acp instanceof AccessControlList) { - acl = ((AccessControlList) acp); - break applicablePolicies; - } - } - } else { - AccessControlPolicy[] existingPolicies = acm.getPolicies(path); - existingPolicies: for (AccessControlPolicy acp : existingPolicies) { - if (acp instanceof AccessControlList) { - acl = ((AccessControlList) acp); - break existingPolicies; - } - } - } - if (acl != null) - return acl; - else - throw new IllegalArgumentException("ACL not found at " + path); - } - - /** Clear authorizations for a user at this path */ - public synchronized static void clearAccessControList(Session session, String path, String username) - throws RepositoryException { - AccessControlManager acm = session.getAccessControlManager(); - AccessControlList acl = getAccessControlList(acm, path); - for (AccessControlEntry ace : acl.getAccessControlEntries()) { - if (ace.getPrincipal().getName().equals(username)) { - acl.removeAccessControlEntry(ace); - } - } - // the new access control list must be applied otherwise this call: - // acl.removeAccessControlEntry(ace); has no effect - acm.setPolicy(path, acl); - session.refresh(true); - session.save(); - } - - /* - * FILES UTILITIES - */ - /** - * Creates the nodes making the path as {@link NodeType#NT_FOLDER} - */ - public static Node mkfolders(Session session, String path) { - return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER, false); - } - - /** - * Copy only nt:folder and nt:file, without their additional types and - * properties. - * - * @param recursive if true copies folders as well, otherwise only first level - * files - * @return how many files were copied - */ - public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, JcrMonitor monitor, boolean onlyAdd) { - long count = 0l; - - // Binary binary = null; - // InputStream in = null; - try { - NodeIterator fromChildren = fromNode.getNodes(); - children: while (fromChildren.hasNext()) { - if (monitor != null && monitor.isCanceled()) - throw new IllegalStateException("Copy cancelled before it was completed"); - - Node fromChild = fromChildren.nextNode(); - String fileName = fromChild.getName(); - if (fromChild.isNodeType(NodeType.NT_FILE)) { - if (onlyAdd && toNode.hasNode(fileName)) { - monitor.subTask("Skip existing " + fileName); - continue children; - } - - if (monitor != null) - monitor.subTask("Copy " + fileName); - try (Bin binary = new Bin(fromChild.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA)); - InputStream in = binary.getStream();) { - copyStreamAsFile(toNode, fileName, in); - } catch (IOException e) { - throw new RuntimeException("Cannot copy " + fileName + " to " + toNode, e); - } - - // save session - toNode.getSession().save(); - count++; - -// if (log.isDebugEnabled()) -// log.debug("Copied file " + fromChild.getPath()); - if (monitor != null) - monitor.worked(1); - } else if (fromChild.isNodeType(NodeType.NT_FOLDER) && recursive) { - Node toChildFolder; - if (toNode.hasNode(fileName)) { - toChildFolder = toNode.getNode(fileName); - if (!toChildFolder.isNodeType(NodeType.NT_FOLDER)) - throw new IllegalArgumentException(toChildFolder + " is not of type nt:folder"); - } else { - toChildFolder = toNode.addNode(fileName, NodeType.NT_FOLDER); - - // save session - toNode.getSession().save(); - } - count = count + copyFiles(fromChild, toChildFolder, recursive, monitor, onlyAdd); - } - } - return count; - } catch (RepositoryException e) { - throw new JcrException("Cannot copy files between " + fromNode + " and " + toNode, e); - } finally { - // in case there was an exception - // IOUtils.closeQuietly(in); - // closeQuietly(binary); - } - } - - /** - * Iteratively count all file nodes in subtree, inefficient but can be useful - * when query are poorly supported, such as in remoting. - */ - public static Long countFiles(Node node) { - Long localCount = 0l; - try { - for (NodeIterator nit = node.getNodes(); nit.hasNext();) { - Node child = nit.nextNode(); - if (child.isNodeType(NodeType.NT_FOLDER)) - localCount = localCount + countFiles(child); - else if (child.isNodeType(NodeType.NT_FILE)) - localCount = localCount + 1; - } - } catch (RepositoryException e) { - throw new JcrException("Cannot count all children of " + node, e); - } - return localCount; - } - - /** - * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session is - * NOT saved. - * - * @return the created file node - */ - @Deprecated - public static Node copyFile(Node folderNode, File file) { - try (InputStream in = new FileInputStream(file)) { - return copyStreamAsFile(folderNode, file.getName(), in); - } catch (IOException e) { - throw new RuntimeException("Cannot copy file " + file + " under " + folderNode, e); - } - } - - /** Copy bytes as an nt:file */ - public static Node copyBytesAsFile(Node folderNode, String fileName, byte[] bytes) { - // InputStream in = null; - try (InputStream in = new ByteArrayInputStream(bytes)) { - // in = new ByteArrayInputStream(bytes); - return copyStreamAsFile(folderNode, fileName, in); - } catch (IOException e) { - throw new RuntimeException("Cannot copy file " + fileName + " under " + folderNode, e); - // } finally { - // IOUtils.closeQuietly(in); - } - } - - /** - * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session is - * NOT saved. - * - * @return the created file node - */ - public static Node copyStreamAsFile(Node folderNode, String fileName, InputStream in) { - Binary binary = null; - try { - Node fileNode; - Node contentNode; - if (folderNode.hasNode(fileName)) { - fileNode = folderNode.getNode(fileName); - if (!fileNode.isNodeType(NodeType.NT_FILE)) - throw new IllegalArgumentException(fileNode + " is not of type nt:file"); - // we assume that the content node is already there - contentNode = fileNode.getNode(Node.JCR_CONTENT); - } else { - fileNode = folderNode.addNode(fileName, NodeType.NT_FILE); - contentNode = fileNode.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED); - } - binary = contentNode.getSession().getValueFactory().createBinary(in); - contentNode.setProperty(Property.JCR_DATA, binary); - updateLastModified(contentNode); - return fileNode; - } catch (RepositoryException e) { - throw new JcrException("Cannot create file node " + fileName + " under " + folderNode, e); - } finally { - closeQuietly(binary); - } - } - - /** Read an an nt:file as an {@link InputStream}. */ - public static InputStream getFileAsStream(Node fileNode) throws RepositoryException { - return fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary().getStream(); - } - - /** - * Set the properties of {@link NodeType#MIX_MIMETYPE} on the content of this - * file node. - */ - public static void setFileMimeType(Node fileNode, String mimeType, String encoding) throws RepositoryException { - Node contentNode = fileNode.getNode(Node.JCR_CONTENT); - if (mimeType != null) - contentNode.setProperty(Property.JCR_MIMETYPE, mimeType); - if (encoding != null) - contentNode.setProperty(Property.JCR_ENCODING, encoding); - // TODO remove properties if args are null? - } - - public static void copyFilesToFs(Node baseNode, Path targetDir, boolean recursive) { - try { - Files.createDirectories(targetDir); - for (NodeIterator nit = baseNode.getNodes(); nit.hasNext();) { - Node node = nit.nextNode(); - if (node.isNodeType(NodeType.NT_FILE)) { - Path filePath = targetDir.resolve(node.getName()); - try (OutputStream out = Files.newOutputStream(filePath); InputStream in = getFileAsStream(node)) { - IOUtils.copy(in, out); - } - } else if (recursive && node.isNodeType(NodeType.NT_FOLDER)) { - Path dirPath = targetDir.resolve(node.getName()); - copyFilesToFs(node, dirPath, true); - } - } - } catch (RepositoryException e) { - throw new JcrException("Cannot copy " + baseNode + " to " + targetDir, e); - } catch (IOException e) { - throw new RuntimeException("Cannot copy " + baseNode + " to " + targetDir, e); - } - } - - /** - * Computes the checksum of an nt:file. - * - * @deprecated use separate digest utilities - */ - @Deprecated - public static String checksumFile(Node fileNode, String algorithm) { - try (InputStream in = fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary() - .getStream()) { - return digest(algorithm, in); - } catch (IOException e) { - throw new RuntimeException("Cannot checksum file " + fileNode + " with algorithm " + algorithm, e); - } catch (RepositoryException e) { - throw new JcrException("Cannot checksum file " + fileNode + " with algorithm " + algorithm, e); - } - } - - @Deprecated - private static String digest(String algorithm, InputStream in) { - final Integer byteBufferCapacity = 100 * 1024;// 100 KB - try { - MessageDigest digest = MessageDigest.getInstance(algorithm); - byte[] buffer = new byte[byteBufferCapacity]; - int read = 0; - while ((read = in.read(buffer)) > 0) { - digest.update(buffer, 0, read); - } - - byte[] checksum = digest.digest(); - String res = encodeHexString(checksum); - return res; - } catch (IOException e) { - throw new RuntimeException("Cannot digest with algorithm " + algorithm, e); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e); - } - } - - /** - * From - * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to - * -a-hex-string-in-java - */ - @Deprecated - private static String encodeHexString(byte[] bytes) { - final char[] hexArray = "0123456789abcdef".toCharArray(); - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - /** Export a subtree as a compact XML without namespaces. */ - public static void toSimpleXml(Node node, StringBuilder sb) throws RepositoryException { - sb.append('<'); - String nodeName = node.getName(); - int colIndex = nodeName.indexOf(':'); - if (colIndex > 0) { - nodeName = nodeName.substring(colIndex + 1); - } - sb.append(nodeName); - PropertyIterator pit = node.getProperties(); - properties: while (pit.hasNext()) { - Property p = pit.nextProperty(); - // skip multiple properties - if (p.isMultiple()) - continue properties; - String propertyName = p.getName(); - int pcolIndex = propertyName.indexOf(':'); - // skip properties with namespaces - if (pcolIndex > 0) - continue properties; - // skip binaries - if (p.getType() == PropertyType.BINARY) { - continue properties; - // TODO retrieve identifier? - } - sb.append(' '); - sb.append(propertyName); - sb.append('='); - sb.append('\"').append(p.getString()).append('\"'); - } - - if (node.hasNodes()) { - sb.append('>'); - NodeIterator children = node.getNodes(); - while (children.hasNext()) { - toSimpleXml(children.nextNode(), sb); - } - sb.append("'); - } else { - sb.append("/>"); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxApi.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxApi.java deleted file mode 100644 index 666b2593e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxApi.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.argeo.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -/** Uilities around the JCR extensions. */ -public class JcrxApi { - public final static String MD5 = "MD5"; - public final static String SHA1 = "SHA1"; - public final static String SHA256 = "SHA-256"; - public final static String SHA512 = "SHA-512"; - - public final static String EMPTY_MD5 = "d41d8cd98f00b204e9800998ecf8427e"; - public final static String EMPTY_SHA1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; - public final static String EMPTY_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - public final static String EMPTY_SHA512 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; - - public final static int LENGTH_MD5 = EMPTY_MD5.length(); - public final static int LENGTH_SHA1 = EMPTY_SHA1.length(); - public final static int LENGTH_SHA256 = EMPTY_SHA256.length(); - public final static int LENGTH_SHA512 = EMPTY_SHA512.length(); - - /* - * XML - */ - /** - * Get the XML text of this child node. - */ - public static String getXmlValue(Node node, String name) { - try { - if (!node.hasNode(name)) - return null; - Node child = node.getNode(name); - return getXmlValue(child); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get " + name + " as XML text", e); - } - } - - /** - * Get the XML text of this node. - */ - public static String getXmlValue(Node node) { - try { - if (!node.hasNode(Jcr.JCR_XMLTEXT)) - return null; - Node xmlText = node.getNode(Jcr.JCR_XMLTEXT); - if (!xmlText.hasProperty(Jcr.JCR_XMLCHARACTERS)) - throw new IllegalArgumentException( - "Node " + xmlText + " has no " + Jcr.JCR_XMLCHARACTERS + " property"); - return xmlText.getProperty(Jcr.JCR_XMLCHARACTERS).getString(); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get " + node + " as XML text", e); - } - } - - /** - * Set as a subnode which will be exported as an XML element. - */ - public static void setXmlValue(Node node, String name, String value) { - try { - if (node.hasNode(name)) { - Node child = node.getNode(name); - setXmlValue(node, child, value); - } else - node.addNode(name, JcrxType.JCRX_XMLVALUE).addNode(Jcr.JCR_XMLTEXT, JcrxType.JCRX_XMLTEXT) - .setProperty(Jcr.JCR_XMLCHARACTERS, value); - } catch (RepositoryException e) { - throw new JcrException("Cannot set " + name + " as XML text", e); - } - } - - public static void setXmlValue(Node node, Node child, String value) { - try { - if (!child.hasNode(Jcr.JCR_XMLTEXT)) - child.addNode(Jcr.JCR_XMLTEXT, JcrxType.JCRX_XMLTEXT); - child.getNode(Jcr.JCR_XMLTEXT).setProperty(Jcr.JCR_XMLCHARACTERS, value); - } catch (RepositoryException e) { - throw new JcrException("Cannot set " + child + " as XML text", e); - } - } - - /** - * Add a checksum replacing the one which was previously set with the same - * length. - */ - public static void addChecksum(Node node, String checksum) { - try { - if (!node.hasProperty(JcrxName.JCRX_SUM)) { - node.setProperty(JcrxName.JCRX_SUM, new String[] { checksum }); - return; - } else { - int stringLength = checksum.length(); - Property property = node.getProperty(JcrxName.JCRX_SUM); - List values = Arrays.asList(property.getValues()); - Integer indexToRemove = null; - values: for (int i = 0; i < values.size(); i++) { - Value value = values.get(i); - if (value.getString().length() == stringLength) { - indexToRemove = i; - break values; - } - } - if (indexToRemove != null) - values.set(indexToRemove, node.getSession().getValueFactory().createValue(checksum)); - else - values.add(0, node.getSession().getValueFactory().createValue(checksum)); - property.setValue(values.toArray(new Value[values.size()])); - } - } catch (RepositoryException e) { - throw new JcrException("Cannot set checksum on " + node, e); - } - } - - /** Replace all checksums. */ - public static void setChecksums(Node node, List checksums) { - try { - node.setProperty(JcrxName.JCRX_SUM, checksums.toArray(new String[checksums.size()])); - } catch (RepositoryException e) { - throw new JcrException("Cannot set checksums on " + node, e); - } - } - - /** Replace all checksums. */ - public static List getChecksums(Node node) { - try { - List res = new ArrayList<>(); - if (!node.hasProperty(JcrxName.JCRX_SUM)) - return res; - Property property = node.getProperty(JcrxName.JCRX_SUM); - for (Value value : property.getValues()) { - res.add(value.getString()); - } - return res; - } catch (RepositoryException e) { - throw new JcrException("Cannot get checksums from " + node, e); - } - } - -// /** Replace all checksums with this single one. */ -// public static void setChecksum(Node node, String checksum) { -// setChecksums(node, Collections.singletonList(checksum)); -// } - - /** Retrieves the checksum with this algorithm, or null if not found. */ - public static String getChecksum(Node node, String algorithm) { - int stringLength; - switch (algorithm) { - case MD5: - stringLength = LENGTH_MD5; - break; - case SHA1: - stringLength = LENGTH_SHA1; - break; - case SHA256: - stringLength = LENGTH_SHA256; - break; - case SHA512: - stringLength = LENGTH_SHA512; - break; - default: - throw new IllegalArgumentException("Unkown algorithm " + algorithm); - } - return getChecksum(node, stringLength); - } - - /** Retrieves the checksum with this string length, or null if not found. */ - public static String getChecksum(Node node, int stringLength) { - try { - if (!node.hasProperty(JcrxName.JCRX_SUM)) - return null; - Property property = node.getProperty(JcrxName.JCRX_SUM); - for (Value value : property.getValues()) { - String str = value.getString(); - if (str.length() == stringLength) - return str; - } - return null; - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot get checksum for " + node, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxName.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxName.java deleted file mode 100644 index 9dd43adce..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxName.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.argeo.jcr; - -/** Names declared by the JCR extensions. */ -public interface JcrxName { - /** The multiple property holding various coherent checksums. */ - public final static String JCRX_SUM = "{http://www.argeo.org/ns/jcrx}sum"; -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxType.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxType.java deleted file mode 100644 index 0cbad3341..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/JcrxType.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.argeo.jcr; - -/** Node types declared by the JCR extensions. */ -public interface JcrxType { - /** - * Node type for an XML value, which will be serialized in XML as an element - * containing text. - */ - public final static String JCRX_XMLVALUE = "{http://www.argeo.org/ns/jcrx}xmlvalue"; - - /** Node type for the node containing the text. */ - public final static String JCRX_XMLTEXT = "{http://www.argeo.org/ns/jcrx}xmltext"; - - /** Mixin node type for a set of checksums. */ - public final static String JCRX_CSUM = "{http://www.argeo.org/ns/jcrx}csum"; - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/PropertyDiff.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/PropertyDiff.java deleted file mode 100644 index 71e76fe9b..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/PropertyDiff.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.argeo.jcr; - -import javax.jcr.Value; - -/** The result of the comparison of two JCR properties. */ -public class PropertyDiff { - public final static Integer MODIFIED = 0; - public final static Integer ADDED = 1; - public final static Integer REMOVED = 2; - - private final Integer type; - private final String relPath; - private final Value referenceValue; - private final Value newValue; - - public PropertyDiff(Integer type, String relPath, Value referenceValue, Value newValue) { - super(); - - if (type == MODIFIED) { - if (referenceValue == null || newValue == null) - throw new IllegalArgumentException("Reference and new values must be specified."); - } else if (type == ADDED) { - if (referenceValue != null || newValue == null) - throw new IllegalArgumentException("New value and only it must be specified."); - } else if (type == REMOVED) { - if (referenceValue == null || newValue != null) - throw new IllegalArgumentException("Reference value and only it must be specified."); - } else { - throw new IllegalArgumentException("Unkown diff type " + type); - } - - if (relPath == null) - throw new IllegalArgumentException("Relative path must be specified"); - - this.type = type; - this.relPath = relPath; - this.referenceValue = referenceValue; - this.newValue = newValue; - } - - public Integer getType() { - return type; - } - - public String getRelPath() { - return relPath; - } - - public Value getReferenceValue() { - return referenceValue; - } - - public Value getNewValue() { - return newValue; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/SimplePrincipal.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/SimplePrincipal.java deleted file mode 100644 index 4f42f2d9c..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/SimplePrincipal.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.argeo.jcr; - -import java.security.Principal; - -/** Canonical implementation of a {@link Principal} */ -class SimplePrincipal implements Principal { - private final String name; - - public SimplePrincipal(String name) { - if (name == null) - throw new IllegalArgumentException("Principal name cannot be null"); - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) - return false; - if (obj instanceof Principal) - return name.equals((((Principal) obj).getName())); - return name.equals(obj.toString()); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return new SimplePrincipal(name); - } - - @Override - public String toString() { - return name; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/ThreadBoundJcrSessionFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/ThreadBoundJcrSessionFactory.java deleted file mode 100644 index 2208627ab..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/ThreadBoundJcrSessionFactory.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.argeo.jcr; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.jcr.LoginException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.argeo.api.cms.CmsLog; - -/** Proxy JCR sessions and attach them to calling threads. */ -@Deprecated -public abstract class ThreadBoundJcrSessionFactory { - private final static CmsLog log = CmsLog.getLog(ThreadBoundJcrSessionFactory.class); - - private Repository repository; - /** can be injected as list, only used if repository is null */ - private List repositories; - - private ThreadLocal session = new ThreadLocal(); - private final Session proxiedSession; - /** If workspace is null, default will be used. */ - private String workspace = null; - - private String defaultUsername = "demo"; - private String defaultPassword = "demo"; - private Boolean forceDefaultCredentials = false; - - private boolean active = true; - - // monitoring - private final List threads = Collections.synchronizedList(new ArrayList()); - private final Map activeSessions = Collections.synchronizedMap(new HashMap()); - private MonitoringThread monitoringThread; - - public ThreadBoundJcrSessionFactory() { - Class[] interfaces = { Session.class }; - proxiedSession = (Session) Proxy.newProxyInstance(ThreadBoundJcrSessionFactory.class.getClassLoader(), - interfaces, new JcrSessionInvocationHandler()); - } - - /** Logs in to the repository using various strategies. */ - protected synchronized Session login() { - if (!isActive()) - throw new IllegalStateException("Thread bound session factory inactive"); - - // discard session previously attached to this thread - Thread thread = Thread.currentThread(); - if (activeSessions.containsKey(thread.getId())) { - Session oldSession = activeSessions.remove(thread.getId()); - oldSession.logout(); - session.remove(); - } - - Session newSession = null; - // first try to login without credentials, assuming the underlying login - // module will have dealt with authentication (typically using Spring - // Security) - if (!forceDefaultCredentials) - try { - newSession = repository().login(workspace); - } catch (LoginException e1) { - log.warn("Cannot login without credentials: " + e1.getMessage()); - // invalid credentials, go to the next step - } catch (RepositoryException e1) { - // other kind of exception, fail - throw new JcrException("Cannot log in to repository", e1); - } - - // log using default username / password (useful for testing purposes) - if (newSession == null) - try { - SimpleCredentials sc = new SimpleCredentials(defaultUsername, defaultPassword.toCharArray()); - newSession = repository().login(sc, workspace); - } catch (RepositoryException e) { - throw new JcrException("Cannot log in to repository", e); - } - - session.set(newSession); - // Log and monitor new session - if (log.isTraceEnabled()) - log.trace("Logged in to JCR session " + newSession + "; userId=" + newSession.getUserID()); - - // monitoring - activeSessions.put(thread.getId(), newSession); - threads.add(thread); - return newSession; - } - - public Object getObject() { - return proxiedSession; - } - - public void init() throws Exception { - // log.error("SHOULD NOT BE USED ANYMORE"); - monitoringThread = new MonitoringThread(); - monitoringThread.start(); - } - - public void dispose() throws Exception { - // if (activeSessions.size() == 0) - // return; - - if (log.isTraceEnabled()) - log.trace("Cleaning up " + activeSessions.size() + " active JCR sessions..."); - - deactivate(); - for (Session sess : activeSessions.values()) { - JcrUtils.logoutQuietly(sess); - } - activeSessions.clear(); - } - - protected Boolean isActive() { - return active; - } - - protected synchronized void deactivate() { - active = false; - notifyAll(); - } - - protected synchronized void removeSession(Thread thread) { - if (!isActive()) - return; - activeSessions.remove(thread.getId()); - threads.remove(thread); - } - - protected synchronized void cleanDeadThreads() { - if (!isActive()) - return; - Iterator it = threads.iterator(); - while (it.hasNext()) { - Thread thread = it.next(); - if (!thread.isAlive() && isActive()) { - if (activeSessions.containsKey(thread.getId())) { - Session session = activeSessions.get(thread.getId()); - activeSessions.remove(thread.getId()); - session.logout(); - if (log.isTraceEnabled()) - log.trace("Cleaned up JCR session (userID=" + session.getUserID() + ") from dead thread " - + thread.getId()); - } - it.remove(); - } - } - try { - wait(1000); - } catch (InterruptedException e) { - // silent - } - } - - public Class getObjectType() { - return Session.class; - } - - public boolean isSingleton() { - return true; - } - - /** - * Called before a method is actually called, allowing to check the session or - * re-login it (e.g. if authentication has changed). The default implementation - * returns the session. - */ - protected Session preCall(Session session) { - return session; - } - - protected Repository repository() { - if (repository != null) - return repository; - if (repositories != null) { - // hardened for OSGi dynamic services - Iterator it = repositories.iterator(); - if (it.hasNext()) - return it.next(); - } - throw new IllegalStateException("No repository injected"); - } - - // /** Useful for declarative registration of OSGi services (blueprint) */ - // public void register(Repository repository, Map params) { - // this.repository = repository; - // } - // - // /** Useful for declarative registration of OSGi services (blueprint) */ - // public void unregister(Repository repository, Map params) { - // this.repository = null; - // } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setRepositories(List repositories) { - this.repositories = repositories; - } - - public void setDefaultUsername(String defaultUsername) { - this.defaultUsername = defaultUsername; - } - - public void setDefaultPassword(String defaultPassword) { - this.defaultPassword = defaultPassword; - } - - public void setForceDefaultCredentials(Boolean forceDefaultCredentials) { - this.forceDefaultCredentials = forceDefaultCredentials; - } - - public void setWorkspace(String workspace) { - this.workspace = workspace; - } - - protected class JcrSessionInvocationHandler implements InvocationHandler { - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable, RepositoryException { - Session threadSession = session.get(); - if (threadSession == null) { - if ("logout".equals(method.getName()))// no need to login - return Void.TYPE; - else if ("toString".equals(method.getName()))// maybe logging - return "Uninitialized Argeo thread bound JCR session"; - threadSession = login(); - } - - preCall(threadSession); - Object ret; - try { - ret = method.invoke(threadSession, args); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RepositoryException) - throw (RepositoryException) cause; - else - throw cause; - } - if ("logout".equals(method.getName())) { - session.remove(); - Thread thread = Thread.currentThread(); - removeSession(thread); - if (log.isTraceEnabled()) - log.trace("Logged out JCR session (userId=" + threadSession.getUserID() + ") on thread " - + thread.getId()); - } - return ret; - } - } - - /** Monitors registered thread in order to clean up dead ones. */ - private class MonitoringThread extends Thread { - - public MonitoringThread() { - super("ThreadBound JCR Session Monitor"); - } - - @Override - public void run() { - while (isActive()) { - cleanDeadThreads(); - } - } - - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/VersionDiff.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/VersionDiff.java deleted file mode 100644 index dab55548b..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/VersionDiff.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.argeo.jcr; - -import java.util.Calendar; -import java.util.Map; - -/** - * Generic Object that enables the creation of history reports based on a JCR - * versionable node. userId and creation date are added to the map of - * PropertyDiff. - * - * These two fields might be null - * - */ -public class VersionDiff { - - private String userId; - private Map diffs; - private Calendar updateTime; - - public VersionDiff(String userId, Calendar updateTime, - Map diffs) { - this.userId = userId; - this.updateTime = updateTime; - this.diffs = diffs; - } - - public String getUserId() { - return userId; - } - - public Map getDiffs() { - return diffs; - } - - public Calendar getUpdateTime() { - return updateTime; - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/BinaryChannel.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/BinaryChannel.java deleted file mode 100644 index d6550feee..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/BinaryChannel.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.argeo.jcr.fs; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.jcr.JcrUtils; - -/** A read/write {@link SeekableByteChannel} based on a {@link Binary}. */ -public class BinaryChannel implements SeekableByteChannel { - private final Node file; - private Binary binary; - private boolean open = true; - - private long position = 0; - - private FileChannel fc = null; - - public BinaryChannel(Node file, Path path) throws RepositoryException, IOException { - this.file = file; - Session session = file.getSession(); - synchronized (session) { - if (file.isNodeType(NodeType.NT_FILE)) { - if (file.hasNode(Node.JCR_CONTENT)) { - Node data = file.getNode(Property.JCR_CONTENT); - this.binary = data.getProperty(Property.JCR_DATA).getBinary(); - } else { - Node data = file.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED); - data.addMixin(NodeType.MIX_LAST_MODIFIED); - try (InputStream in = new ByteArrayInputStream(new byte[0])) { - this.binary = data.getSession().getValueFactory().createBinary(in); - } - data.setProperty(Property.JCR_DATA, this.binary); - - // MIME type - String mime = Files.probeContentType(path); - // String mime = fileTypeMap.getContentType(file.getName()); - data.setProperty(Property.JCR_MIMETYPE, mime); - - session.refresh(true); - session.save(); - session.notifyAll(); - } - } else { - throw new IllegalArgumentException( - "Unsupported file node " + file + " (" + file.getPrimaryNodeType() + ")"); - } - } - } - - @Override - public synchronized boolean isOpen() { - return open; - } - - @Override - public synchronized void close() throws IOException { - if (isModified()) { - Binary newBinary = null; - try { - Session session = file.getSession(); - synchronized (session) { - fc.position(0); - InputStream in = Channels.newInputStream(fc); - newBinary = session.getValueFactory().createBinary(in); - file.getNode(Property.JCR_CONTENT).setProperty(Property.JCR_DATA, newBinary); - session.refresh(true); - session.save(); - open = false; - session.notifyAll(); - } - } catch (RepositoryException e) { - throw new IOException("Cannot close " + file, e); - } finally { - JcrUtils.closeQuietly(newBinary); - // IOUtils.closeQuietly(fc); - if (fc != null) { - fc.close(); - } - } - } else { - clearReadState(); - open = false; - } - } - - @Override - public int read(ByteBuffer dst) throws IOException { - if (isModified()) { - return fc.read(dst); - } else { - - try { - int read; - byte[] arr = dst.array(); - read = binary.read(arr, position); - - if (read != -1) - position = position + read; - return read; - } catch (RepositoryException e) { - throw new IOException("Cannot read into buffer", e); - } - } - } - - @Override - public int write(ByteBuffer src) throws IOException { - int written = getFileChannel().write(src); - return written; - } - - @Override - public long position() throws IOException { - if (isModified()) - return getFileChannel().position(); - else - return position; - } - - @Override - public SeekableByteChannel position(long newPosition) throws IOException { - if (isModified()) { - getFileChannel().position(position); - } else { - this.position = newPosition; - } - return this; - } - - @Override - public long size() throws IOException { - if (isModified()) { - return getFileChannel().size(); - } else { - try { - return binary.getSize(); - } catch (RepositoryException e) { - throw new IOException("Cannot get size", e); - } - } - } - - @Override - public SeekableByteChannel truncate(long size) throws IOException { - getFileChannel().truncate(size); - return this; - } - - private FileChannel getFileChannel() throws IOException { - try { - if (fc == null) { - Path tempPath = Files.createTempFile(getClass().getSimpleName(), null); - fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ, - StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.SPARSE); - ReadableByteChannel readChannel = Channels.newChannel(binary.getStream()); - fc.transferFrom(readChannel, 0, binary.getSize()); - clearReadState(); - } - return fc; - } catch (RepositoryException e) { - throw new IOException("Cannot get temp file channel", e); - } - } - - private boolean isModified() { - return fc != null; - } - - private void clearReadState() { - position = -1; - JcrUtils.closeQuietly(binary); - binary = null; - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrBasicfileAttributes.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrBasicfileAttributes.java deleted file mode 100644 index 7c9711bf0..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrBasicfileAttributes.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.argeo.jcr.fs; - -import static javax.jcr.Property.JCR_CREATED; -import static javax.jcr.Property.JCR_LAST_MODIFIED; - -import java.nio.file.attribute.FileTime; -import java.time.Instant; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.jcr.JcrUtils; - -public class JcrBasicfileAttributes implements NodeFileAttributes { - private final Node node; - - private final static FileTime EPOCH = FileTime.fromMillis(0); - - public JcrBasicfileAttributes(Node node) { - if (node == null) - throw new JcrFsException("Node underlying the attributes cannot be null"); - this.node = node; - } - - @Override - public FileTime lastModifiedTime() { - try { - if (node.hasProperty(JCR_LAST_MODIFIED)) { - Instant instant = node.getProperty(JCR_LAST_MODIFIED).getDate().toInstant(); - return FileTime.from(instant); - } else if (node.hasProperty(JCR_CREATED)) { - Instant instant = node.getProperty(JCR_CREATED).getDate().toInstant(); - return FileTime.from(instant); - } -// if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) { -// Instant instant = node.getProperty(Property.JCR_LAST_MODIFIED).getDate().toInstant(); -// return FileTime.from(instant); -// } - return EPOCH; - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get last modified time", e); - } - } - - @Override - public FileTime lastAccessTime() { - return lastModifiedTime(); - } - - @Override - public FileTime creationTime() { - try { - if (node.hasProperty(JCR_CREATED)) { - Instant instant = node.getProperty(JCR_CREATED).getDate().toInstant(); - return FileTime.from(instant); - } else if (node.hasProperty(JCR_LAST_MODIFIED)) { - Instant instant = node.getProperty(JCR_LAST_MODIFIED).getDate().toInstant(); - return FileTime.from(instant); - } -// if (node.isNodeType(NodeType.MIX_CREATED)) { -// Instant instant = node.getProperty(JCR_CREATED).getDate().toInstant(); -// return FileTime.from(instant); -// } - return EPOCH; - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get creation time", e); - } - } - - @Override - public boolean isRegularFile() { - try { - return node.isNodeType(NodeType.NT_FILE); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot check if regular file", e); - } - } - - @Override - public boolean isDirectory() { - try { - if (node.isNodeType(NodeType.NT_FOLDER)) - return true; - // all other non file nodes - return !(node.isNodeType(NodeType.NT_FILE) || node.isNodeType(NodeType.NT_LINKED_FILE)); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot check if directory", e); - } - } - - @Override - public boolean isSymbolicLink() { - try { - return node.isNodeType(NodeType.NT_LINKED_FILE); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot check if linked file", e); - } - } - - @Override - public boolean isOther() { - return !(isDirectory() || isRegularFile() || isSymbolicLink()); - } - - @Override - public long size() { - if (isRegularFile()) { - Binary binary = null; - try { - binary = node.getNode(Property.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary(); - return binary.getSize(); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot check size", e); - } finally { - JcrUtils.closeQuietly(binary); - } - } - return -1; - } - - @Override - public Object fileKey() { - try { - return node.getIdentifier(); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get identifier", e); - } - } - - @Override - public Node getNode() { - return node; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystem.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystem.java deleted file mode 100644 index 4b329810f..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystem.java +++ /dev/null @@ -1,252 +0,0 @@ -package org.argeo.jcr.fs; - -import java.io.IOException; -import java.nio.file.FileStore; -import java.nio.file.FileSystem; -import java.nio.file.Path; -import java.nio.file.PathMatcher; -import java.nio.file.WatchService; -import java.nio.file.attribute.UserPrincipalLookupService; -import java.nio.file.spi.FileSystemProvider; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import javax.jcr.Credentials; -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.api.acr.fs.AbstractFsStore; -import org.argeo.api.acr.fs.AbstractFsSystem; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrUtils; - -public class JcrFileSystem extends AbstractFsSystem { - private final JcrFileSystemProvider provider; - - private final Repository repository; - private Session session; - private WorkspaceFileStore baseFileStore; - - private Map mounts = new TreeMap<>(); - - private String userHomePath = null; - - @Deprecated - public JcrFileSystem(JcrFileSystemProvider provider, Session session) throws IOException { - super(); - this.provider = provider; - baseFileStore = new WorkspaceFileStore(null, session.getWorkspace()); - this.session = session; -// Node userHome = provider.getUserHome(session); -// if (userHome != null) -// try { -// userHomePath = userHome.getPath(); -// } catch (RepositoryException e) { -// throw new IOException("Cannot retrieve user home path", e); -// } - this.repository = null; - } - - public JcrFileSystem(JcrFileSystemProvider provider, Repository repository) throws IOException { - this(provider, repository, null); - } - - public JcrFileSystem(JcrFileSystemProvider provider, Repository repository, Credentials credentials) - throws IOException { - super(); - this.provider = provider; - this.repository = repository; - try { - this.session = credentials == null ? repository.login() : repository.login(credentials); - baseFileStore = new WorkspaceFileStore(null, session.getWorkspace()); - workspaces: for (String workspaceName : baseFileStore.getWorkspace().getAccessibleWorkspaceNames()) { - if (workspaceName.equals(baseFileStore.getWorkspace().getName())) - continue workspaces;// do not mount base - if (workspaceName.equals("security")) { - continue workspaces;// do not mount security workspace - // TODO make it configurable - } - Session mountSession = credentials == null ? repository.login(workspaceName) - : repository.login(credentials, workspaceName); - String mountPath = JcrPath.separator + workspaceName; - mounts.put(mountPath, new WorkspaceFileStore(mountPath, mountSession.getWorkspace())); - } - } catch (RepositoryException e) { - throw new IOException("Cannot initialise file system", e); - } - - Node userHome = provider.getUserHome(repository); - if (userHome != null) - try { - userHomePath = toFsPath(userHome); - } catch (RepositoryException e) { - throw new IOException("Cannot retrieve user home path", e); - } finally { - JcrUtils.logoutQuietly(Jcr.session(userHome)); - } - } - - public String toFsPath(Node node) throws RepositoryException { - return getFileStore(node).toFsPath(node); - } - - /** Whether this node should be skipped in directory listings */ - public boolean skipNode(Node node) throws RepositoryException { - if (node.isNodeType(NodeType.NT_HIERARCHY_NODE)) - return false; - return true; - } - - public String getUserHomePath() { - return userHomePath; - } - - public WorkspaceFileStore getFileStore(String path) { - WorkspaceFileStore res = baseFileStore; - for (String mountPath : mounts.keySet()) { - if (path.equals(mountPath)) - return mounts.get(mountPath); - if (path.startsWith(mountPath + JcrPath.separator)) { - res = mounts.get(mountPath); - // we keep the last one - } - } - assert res != null; - return res; - } - - public WorkspaceFileStore getFileStore(Node node) throws RepositoryException { - String workspaceName = node.getSession().getWorkspace().getName(); - if (workspaceName.equals(baseFileStore.getWorkspace().getName())) - return baseFileStore; - for (String mountPath : mounts.keySet()) { - WorkspaceFileStore fileStore = mounts.get(mountPath); - if (workspaceName.equals(fileStore.getWorkspace().getName())) - return fileStore; - } - throw new IllegalStateException("No workspace mount found for " + node + " in workspace " + workspaceName); - } - - public Iterator listDirectMounts(Path base) { - String baseStr = base.toString(); - Set res = new HashSet<>(); - mounts: for (String mountPath : mounts.keySet()) { - if (mountPath.equals(baseStr)) - continue mounts; - if (mountPath.startsWith(baseStr)) { - JcrPath path = new JcrPath(this, mountPath); - Path relPath = base.relativize(path); - if (relPath.getNameCount() == 1) - res.add(path); - } - } - return res.iterator(); - } - - public WorkspaceFileStore getBaseFileStore() { - return baseFileStore; - } - - @Override - public FileSystemProvider provider() { - return provider; - } - - @Override - public void close() throws IOException { - JcrUtils.logoutQuietly(session); - for (String mountPath : mounts.keySet()) { - WorkspaceFileStore fileStore = mounts.get(mountPath); - try { - fileStore.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Override - public boolean isOpen() { - return session.isLive(); - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - public String getSeparator() { - return JcrPath.separator; - } - - @Override - public Iterable getRootDirectories() { - Set single = new HashSet<>(); - single.add(new JcrPath(this, JcrPath.separator)); - return single; - } - - @Override - public Iterable getFileStores() { - List stores = new ArrayList<>(); - stores.add(baseFileStore); - stores.addAll(mounts.values()); - return stores; - } - - @Override - public Set supportedFileAttributeViews() { - try { - String[] prefixes = session.getNamespacePrefixes(); - Set res = new HashSet<>(); - for (String prefix : prefixes) - res.add(prefix); - res.add("basic"); - return res; - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get supported file attributes views", e); - } - } - - @Override - public Path getPath(String first, String... more) { - StringBuilder sb = new StringBuilder(first); - // TODO Make it more robust - for (String part : more) - sb.append('/').append(part); - return new JcrPath(this, sb.toString()); - } - - @Override - public PathMatcher getPathMatcher(String syntaxAndPattern) { - throw new UnsupportedOperationException(); - } - - @Override - public UserPrincipalLookupService getUserPrincipalLookupService() { - throw new UnsupportedOperationException(); - } - - @Override - public WatchService newWatchService() throws IOException { - throw new UnsupportedOperationException(); - } - -// public Session getSession() { -// return session; -// } - - public Repository getRepository() { - return repository; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java deleted file mode 100644 index 74d9a198e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java +++ /dev/null @@ -1,337 +0,0 @@ -package org.argeo.jcr.fs; - -import java.io.IOException; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.AccessMode; -import java.nio.file.CopyOption; -import java.nio.file.DirectoryNotEmptyException; -import java.nio.file.DirectoryStream; -import java.nio.file.DirectoryStream.Filter; -import java.nio.file.FileStore; -import java.nio.file.LinkOption; -import java.nio.file.NoSuchFileException; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.spi.FileSystemProvider; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.nodetype.PropertyDefinition; - -import org.argeo.jcr.JcrUtils; - -/** Operations on a {@link JcrFileSystem}. */ -public abstract class JcrFileSystemProvider extends FileSystemProvider { - - @Override - public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) - throws IOException { - Node node = toNode(path); - try { - if (node == null) { - Node parent = toNode(path.getParent()); - if (parent == null) - throw new IOException("No parent directory for " + path); - if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE) - || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE)) - throw new IOException(path + " parent is a file"); - - String fileName = path.getFileName().toString(); - fileName = Text.escapeIllegalJcrChars(fileName); - node = parent.addNode(fileName, NodeType.NT_FILE); - node.addMixin(NodeType.MIX_CREATED); -// node.addMixin(NodeType.MIX_LAST_MODIFIED); - } - if (!node.isNodeType(NodeType.NT_FILE)) - throw new UnsupportedOperationException(node + " must be a file"); - return new BinaryChannel(node, path); - } catch (RepositoryException e) { - discardChanges(node); - throw new IOException("Cannot read file", e); - } - } - - @Override - public DirectoryStream newDirectoryStream(Path dir, Filter filter) throws IOException { - try { - Node base = toNode(dir); - if (base == null) - throw new IOException(dir + " is not a JCR node"); - JcrFileSystem fileSystem = (JcrFileSystem) dir.getFileSystem(); - return new NodeDirectoryStream(fileSystem, base.getNodes(), fileSystem.listDirectMounts(dir), filter); - } catch (RepositoryException e) { - throw new IOException("Cannot list directory", e); - } - } - - @Override - public void createDirectory(Path dir, FileAttribute... attrs) throws IOException { - Node node = toNode(dir); - try { - if (node == null) { - Node parent = toNode(dir.getParent()); - if (parent == null) - throw new IOException("Parent of " + dir + " does not exist"); - Session session = parent.getSession(); - synchronized (session) { - if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE) - || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE)) - throw new IOException(dir + " parent is a file"); - String fileName = dir.getFileName().toString(); - fileName = Text.escapeIllegalJcrChars(fileName); - node = parent.addNode(fileName, NodeType.NT_FOLDER); - node.addMixin(NodeType.MIX_CREATED); - node.addMixin(NodeType.MIX_LAST_MODIFIED); - save(session); - } - } else { - // if (!node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) - // throw new FileExistsException(dir + " exists and is not a directory"); - } - } catch (RepositoryException e) { - discardChanges(node); - throw new IOException("Cannot create directory " + dir, e); - } - } - - @Override - public void delete(Path path) throws IOException { - Node node = toNode(path); - try { - if (node == null) - throw new NoSuchFileException(path + " does not exist"); - Session session = node.getSession(); - synchronized (session) { - session.refresh(false); - if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) - node.remove(); - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) { - if (node.hasNodes())// TODO check only files - throw new DirectoryNotEmptyException(path.toString()); - node.remove(); - } - save(session); - } - } catch (RepositoryException e) { - discardChanges(node); - throw new IOException("Cannot delete " + path, e); - } - - } - - @Override - public void copy(Path source, Path target, CopyOption... options) throws IOException { - Node sourceNode = toNode(source); - Node targetNode = toNode(target); - try { - Session targetSession = targetNode.getSession(); - synchronized (targetSession) { - JcrUtils.copy(sourceNode, targetNode); - save(targetSession); - } - } catch (RepositoryException e) { - discardChanges(sourceNode); - discardChanges(targetNode); - throw new IOException("Cannot copy from " + source + " to " + target, e); - } - } - - @Override - public void move(Path source, Path target, CopyOption... options) throws IOException { - JcrFileSystem sourceFileSystem = (JcrFileSystem) source.getFileSystem(); - WorkspaceFileStore sourceStore = sourceFileSystem.getFileStore(source.toString()); - WorkspaceFileStore targetStore = sourceFileSystem.getFileStore(target.toString()); - try { - if (sourceStore.equals(targetStore)) { - sourceStore.getWorkspace().move(sourceStore.toJcrPath(source.toString()), - targetStore.toJcrPath(target.toString())); - } else { - // TODO implement it - throw new UnsupportedOperationException("Can only move paths within the same workspace."); - } - } catch (RepositoryException e) { - throw new IOException("Cannot move from " + source + " to " + target, e); - } - -// Node sourceNode = toNode(source); -// try { -// Session session = sourceNode.getSession(); -// synchronized (session) { -// session.move(sourceNode.getPath(), target.toString()); -// save(session); -// } -// } catch (RepositoryException e) { -// discardChanges(sourceNode); -// throw new IOException("Cannot move from " + source + " to " + target, e); -// } - } - - @Override - public boolean isSameFile(Path path, Path path2) throws IOException { - if (path.getFileSystem() != path2.getFileSystem()) - return false; - boolean equ = path.equals(path2); - if (equ) - return true; - else { - try { - Node node = toNode(path); - Node node2 = toNode(path2); - return node.isSame(node2); - } catch (RepositoryException e) { - throw new IOException("Cannot check whether " + path + " and " + path2 + " are same", e); - } - } - - } - - @Override - public boolean isHidden(Path path) throws IOException { - return path.getFileName().toString().charAt(0) == '.'; - } - - @Override - public FileStore getFileStore(Path path) throws IOException { - JcrFileSystem fileSystem = (JcrFileSystem) path.getFileSystem(); - return fileSystem.getFileStore(path.toString()); - } - - @Override - public void checkAccess(Path path, AccessMode... modes) throws IOException { - Node node = toNode(path); - if (node == null) - throw new NoSuchFileException(path + " does not exist"); - // TODO check access via JCR api - } - - @Override - public V getFileAttributeView(Path path, Class type, LinkOption... options) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("unchecked") - @Override - public A readAttributes(Path path, Class type, LinkOption... options) - throws IOException { - // TODO check if assignable - Node node = toNode(path); - if (node == null) { - throw new IOException("JCR node not found for " + path); - } - return (A) new JcrBasicfileAttributes(node); - } - - @Override - public Map readAttributes(Path path, String attributes, LinkOption... options) throws IOException { - try { - Node node = toNode(path); - String pattern = attributes.replace(',', '|'); - Map res = new HashMap(); - PropertyIterator it = node.getProperties(pattern); - props: while (it.hasNext()) { - Property prop = it.nextProperty(); - PropertyDefinition pd = prop.getDefinition(); - if (pd.isMultiple()) - continue props; - int requiredType = pd.getRequiredType(); - switch (requiredType) { - case PropertyType.LONG: - res.put(prop.getName(), prop.getLong()); - break; - case PropertyType.DOUBLE: - res.put(prop.getName(), prop.getDouble()); - break; - case PropertyType.BOOLEAN: - res.put(prop.getName(), prop.getBoolean()); - break; - case PropertyType.DATE: - res.put(prop.getName(), prop.getDate()); - break; - case PropertyType.BINARY: - byte[] arr = JcrUtils.getBinaryAsBytes(prop); - res.put(prop.getName(), arr); - break; - default: - res.put(prop.getName(), prop.getString()); - } - } - return res; - } catch (RepositoryException e) { - throw new IOException("Cannot read attributes of " + path, e); - } - } - - @Override - public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { - Node node = toNode(path); - try { - Session session = node.getSession(); - synchronized (session) { - if (value instanceof byte[]) { - JcrUtils.setBinaryAsBytes(node, attribute, (byte[]) value); - } else if (value instanceof Calendar) { - node.setProperty(attribute, (Calendar) value); - } else { - node.setProperty(attribute, value.toString()); - } - save(session); - } - } catch (RepositoryException e) { - discardChanges(node); - throw new IOException("Cannot set attribute " + attribute + " on " + path, e); - } - } - - protected Node toNode(Path path) { - try { - return ((JcrPath) path).getNode(); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot convert path " + path + " to JCR Node", e); - } - } - - /** Discard changes in the underlying session */ - protected void discardChanges(Node node) { - if (node == null) - return; - try { - // discard changes - node.getSession().refresh(false); - } catch (RepositoryException e) { - e.printStackTrace(); - // TODO log out session? - // TODO use Commons logging? - } - } - - /** Make sure save is robust. */ - protected void save(Session session) throws RepositoryException { - session.refresh(true); - session.save(); - session.notifyAll(); - } - - /** - * To be overriden in order to support the ~ path, with an implementation - * specific concept of user home. - * - * @return null by default - */ - public Node getUserHome(Repository session) { - return null; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFsException.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFsException.java deleted file mode 100644 index f214fdc44..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrFsException.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.argeo.jcr.fs; - - -/** Exception related to the JCR FS */ -public class JcrFsException extends RuntimeException { - private static final long serialVersionUID = -7973896038244922980L; - - public JcrFsException(String message, Throwable e) { - super(message, e); - } - - public JcrFsException(String message) { - super(message); - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrPath.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrPath.java deleted file mode 100644 index 7318b7096..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/JcrPath.java +++ /dev/null @@ -1,384 +0,0 @@ -package org.argeo.jcr.fs; - -import java.nio.file.Path; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.api.acr.fs.AbstractFsPath; - -/** A {@link Path} which contains a reference to a JCR {@link Node}. */ -public class JcrPath extends AbstractFsPath { - final static String separator = "/"; - final static char separatorChar = '/'; - -// private final JcrFileSystem fs; -// /** null for non absolute paths */ -// private final WorkspaceFileStore fileStore; -// private final String[] path;// null means root -// private final boolean absolute; -// -// // optim -// private final int hashCode; - - public JcrPath(JcrFileSystem filesSystem, String path) { - super(filesSystem, path); -// this.fs = filesSystem; -// if (path == null) -// throw new JcrFsException("Path cannot be null"); -// if (path.equals(separator)) {// root -// this.path = null; -// this.absolute = true; -// this.hashCode = 0; -// this.fileStore = fs.getBaseFileStore(); -// return; -// } else if (path.equals("")) {// empty path -// this.path = new String[] { "" }; -// this.absolute = false; -// this.fileStore = null; -// this.hashCode = "".hashCode(); -// return; -// } -// -// if (path.equals("~")) {// home -// path = filesSystem.getUserHomePath(); -// if (path == null) -// throw new JcrFsException("No home directory available"); -// } -// -// this.absolute = path.charAt(0) == separatorChar ? true : false; -// -// this.fileStore = absolute ? fs.getFileStore(path) : null; -// -// String trimmedPath = path.substring(absolute ? 1 : 0, -// path.charAt(path.length() - 1) == separatorChar ? path.length() - 1 : path.length()); -// this.path = trimmedPath.split(separator); -// for (int i = 0; i < this.path.length; i++) { -// this.path[i] = Text.unescapeIllegalJcrChars(this.path[i]); -// } -// this.hashCode = this.path[this.path.length - 1].hashCode(); -// assert !(absolute && fileStore == null); - } - - public JcrPath(JcrFileSystem filesSystem, Node node) throws RepositoryException { - this(filesSystem, filesSystem.getFileStore(node).toFsPath(node)); - } - - /** Internal optimisation */ - private JcrPath(JcrFileSystem filesSystem, WorkspaceFileStore fileStore, String[] path, boolean absolute) { - super(filesSystem, fileStore, path, absolute); -// this.fs = filesSystem; -// this.path = path; -// this.absolute = path == null ? true : absolute; -// if (this.absolute && fileStore == null) -// throw new IllegalArgumentException("Absolute path requires a file store"); -// if (!this.absolute && fileStore != null) -// throw new IllegalArgumentException("A file store should not be provided for a relative path"); -// this.fileStore = fileStore; -// this.hashCode = path == null ? 0 : path[path.length - 1].hashCode(); -// assert !(absolute && fileStore == null); - } - - protected String cleanUpSegment(String segment) { - return Text.unescapeIllegalJcrChars(segment); - } - - @Override - protected JcrPath newInstance(String path) { - return new JcrPath(getFileSystem(), path); - } - - @Override - protected JcrPath newInstance(String[] segments, boolean absolute) { - return new JcrPath(getFileSystem(), getFileStore(), segments, absolute); - - } - -// @Override -// public FileSystem getFileSystem() { -// return fs; -// } -// -// @Override -// public boolean isAbsolute() { -// return absolute; -// } -// -// @Override -// public Path getRoot() { -// if (path == null) -// return this; -// return new JcrPath(fs, separator); -// } -// -// @Override -// public String toString() { -// return toFsPath(path); -// } -// -// private String toFsPath(String[] path) { -// if (path == null) -// return "/"; -// StringBuilder sb = new StringBuilder(); -// if (isAbsolute()) -// sb.append('/'); -// for (int i = 0; i < path.length; i++) { -// if (i != 0) -// sb.append('/'); -// sb.append(path[i]); -// } -// return sb.toString(); -// } - -// @Deprecated -// private String toJcrPath() { -// return toJcrPath(path); -// } -// -// @Deprecated -// private String toJcrPath(String[] path) { -// if (path == null) -// return "/"; -// StringBuilder sb = new StringBuilder(); -// if (isAbsolute()) -// sb.append('/'); -// for (int i = 0; i < path.length; i++) { -// if (i != 0) -// sb.append('/'); -// sb.append(Text.escapeIllegalJcrChars(path[i])); -// } -// return sb.toString(); -// } - -// @Override -// public Path getFileName() { -// if (path == null) -// return null; -// return new JcrPath(fs, path[path.length - 1]); -// } -// -// @Override -// public Path getParent() { -// if (path == null) -// return null; -// if (path.length == 1)// root -// return new JcrPath(fs, separator); -// String[] parentPath = Arrays.copyOfRange(path, 0, path.length - 1); -// if (!absolute) -// return new JcrPath(fs, null, parentPath, absolute); -// else -// return new JcrPath(fs, toFsPath(parentPath)); -// } -// -// @Override -// public int getNameCount() { -// if (path == null) -// return 0; -// return path.length; -// } -// -// @Override -// public Path getName(int index) { -// if (path == null) -// return null; -// return new JcrPath(fs, path[index]); -// } -// -// @Override -// public Path subpath(int beginIndex, int endIndex) { -// if (path == null) -// return null; -// String[] parentPath = Arrays.copyOfRange(path, beginIndex, endIndex); -// return new JcrPath(fs, null, parentPath, false); -// } -// -// @Override -// public boolean startsWith(Path other) { -// return toString().startsWith(other.toString()); -// } -// -// @Override -// public boolean startsWith(String other) { -// return toString().startsWith(other); -// } -// -// @Override -// public boolean endsWith(Path other) { -// return toString().endsWith(other.toString()); -// } -// -// @Override -// public boolean endsWith(String other) { -// return toString().endsWith(other); -// } - -// @Override -// public Path normalize() { -// // always normalized -// return this; -// } - -// @Override -// public Path resolve(Path other) { -// JcrPath otherPath = (JcrPath) other; -// if (otherPath.isAbsolute()) -// return other; -// String[] newPath; -// if (path == null) { -// newPath = new String[otherPath.path.length]; -// System.arraycopy(otherPath.path, 0, newPath, 0, otherPath.path.length); -// } else { -// newPath = new String[path.length + otherPath.path.length]; -// System.arraycopy(path, 0, newPath, 0, path.length); -// System.arraycopy(otherPath.path, 0, newPath, path.length, otherPath.path.length); -// } -// if (!absolute) -// return new JcrPath(fs, null, newPath, absolute); -// else { -// return new JcrPath(fs, toFsPath(newPath)); -// } -// } -// -// @Override -// public final Path resolve(String other) { -// return resolve(getFileSystem().getPath(other)); -// } -// -// @Override -// public final Path resolveSibling(Path other) { -// if (other == null) -// throw new NullPointerException(); -// Path parent = getParent(); -// return (parent == null) ? other : parent.resolve(other); -// } -// -// @Override -// public final Path resolveSibling(String other) { -// return resolveSibling(getFileSystem().getPath(other)); -// } -// -// @Override -// public final Iterator iterator() { -// return new Iterator() { -// private int i = 0; -// -// @Override -// public boolean hasNext() { -// return (i < getNameCount()); -// } -// -// @Override -// public Path next() { -// if (i < getNameCount()) { -// Path result = getName(i); -// i++; -// return result; -// } else { -// throw new NoSuchElementException(); -// } -// } -// -// @Override -// public void remove() { -// throw new UnsupportedOperationException(); -// } -// }; -// } -// -// @Override -// public Path relativize(Path other) { -// if (equals(other)) -// return new JcrPath(fs, ""); -// if (other.startsWith(this)) { -// String p1 = toString(); -// String p2 = other.toString(); -// String relative = p2.substring(p1.length(), p2.length()); -// if (relative.charAt(0) == '/') -// relative = relative.substring(1); -// return new JcrPath(fs, relative); -// } -// throw new IllegalArgumentException(other + " cannot be relativized against " + this); -// } - -// @Override -// public URI toUri() { -// try { -// return new URI(fs.provider().getScheme(), toString(), null); -// } catch (URISyntaxException e) { -// throw new JcrFsException("Cannot create URI for " + toString(), e); -// } -// } -// -// @Override -// public Path toAbsolutePath() { -// if (isAbsolute()) -// return this; -// return new JcrPath(fs, fileStore, path, true); -// } -// -// @Override -// public Path toRealPath(LinkOption... options) throws IOException { -// return this; -// } -// -// @Override -// public File toFile() { -// throw new UnsupportedOperationException(); -// } - - public Node getNode() throws RepositoryException { - if (!isAbsolute())// TODO default dir - throw new JcrFsException("Cannot get a JCR node from a relative path"); - assert getFileStore() != null; - return getFileStore().toNode(getSegments()); -// String pathStr = toJcrPath(); -// Session session = fs.getSession(); -// // TODO synchronize on the session ? -// if (!session.itemExists(pathStr)) -// return null; -// return session.getNode(pathStr); - } -// -// @Override -// public boolean equals(Object obj) { -// if (!(obj instanceof JcrPath)) -// return false; -// JcrPath other = (JcrPath) obj; -// -// if (path == null) {// root -// if (other.path == null)// root -// return true; -// else -// return false; -// } else { -// if (other.path == null)// root -// return false; -// } -// // non root -// if (path.length != other.path.length) -// return false; -// for (int i = 0; i < path.length; i++) { -// if (!path[i].equals(other.path[i])) -// return false; -// } -// return true; -// } - -// @Override -// public int hashCode() { -// return hashCode; -// } - -// @Override -// protected Object clone() throws CloneNotSupportedException { -// return new JcrPath(fs, toString()); -// } - -// @Override -// protected void finalize() throws Throwable { -// Arrays.fill(path, null); -// } - - - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeDirectoryStream.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeDirectoryStream.java deleted file mode 100644 index eda07a548..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeDirectoryStream.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.argeo.jcr.fs; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Path; -import java.util.Iterator; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; - -public class NodeDirectoryStream implements DirectoryStream { - private final JcrFileSystem fs; - private final NodeIterator nodeIterator; - private final Iterator additionalPaths; - private final Filter filter; - - public NodeDirectoryStream(JcrFileSystem fs, NodeIterator nodeIterator, Iterator additionalPaths, - Filter filter) { - this.fs = fs; - this.nodeIterator = nodeIterator; - this.additionalPaths = additionalPaths; - this.filter = filter; - } - - @Override - public void close() throws IOException { - } - - @Override - public Iterator iterator() { - return new Iterator() { - private JcrPath next = null; - - @Override - public synchronized boolean hasNext() { - if (next != null) - return true; - nodes: while (nodeIterator.hasNext()) { - try { - Node node = nodeIterator.nextNode(); - String nodeName = node.getName(); - if (nodeName.startsWith("rep:") || nodeName.startsWith("jcr:")) - continue nodes; - if (fs.skipNode(node)) - continue nodes; - next = new JcrPath(fs, node); - if (filter != null) { - if (filter.accept(next)) - break nodes; - } else - break nodes; - } catch (Exception e) { - throw new JcrFsException("Could not get next path", e); - } - } - - if (next == null) { - if (additionalPaths.hasNext()) - next = additionalPaths.next(); - } - - return next != null; - } - - @Override - public synchronized Path next() { - if (!hasNext())// make sure has next has been called - return null; - JcrPath res = next; - next = null; - return res; - } - - }; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeFileAttributes.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeFileAttributes.java deleted file mode 100644 index 8054d52f8..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/NodeFileAttributes.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.argeo.jcr.fs; - -import java.nio.file.attribute.BasicFileAttributes; - -import javax.jcr.Node; - -public interface NodeFileAttributes extends BasicFileAttributes { - public Node getNode(); -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/Text.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/Text.java deleted file mode 100644 index 4643c8c9c..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/Text.java +++ /dev/null @@ -1,877 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.jcr.fs; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Properties; - -/** - * Hacked from org.apache.jackrabbit.util.Text in Jackrabbit JCR Commons - * This Class provides some text related utilities - */ -class Text { - - /** - * Hidden constructor. - */ - private Text() { - } - - /** - * used for the md5 - */ - public static final char[] hexTable = "0123456789abcdef".toCharArray(); - - /** - * Calculate an MD5 hash of the string given. - * - * @param data - * the data to encode - * @param enc - * the character encoding to use - * @return a hex encoded string of the md5 digested input - */ - public static String md5(String data, String enc) throws UnsupportedEncodingException { - try { - return digest("MD5", data.getBytes(enc)); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("MD5 digest not available???"); - } - } - - /** - * Calculate an MD5 hash of the string given using 'utf-8' encoding. - * - * @param data - * the data to encode - * @return a hex encoded string of the md5 digested input - */ - public static String md5(String data) { - try { - return md5(data, "utf-8"); - } catch (UnsupportedEncodingException e) { - throw new InternalError("UTF8 digest not available???"); - } - } - - /** - * Digest the plain string using the given algorithm. - * - * @param algorithm - * The alogrithm for the digest. This algorithm must be supported - * by the MessageDigest class. - * @param data - * The plain text String to be digested. - * @param enc - * The character encoding to use - * @return The digested plain text String represented as Hex digits. - * @throws java.security.NoSuchAlgorithmException - * if the desired algorithm is not supported by the - * MessageDigest class. - * @throws java.io.UnsupportedEncodingException - * if the encoding is not supported - */ - public static String digest(String algorithm, String data, String enc) - throws NoSuchAlgorithmException, UnsupportedEncodingException { - - return digest(algorithm, data.getBytes(enc)); - } - - /** - * Digest the plain string using the given algorithm. - * - * @param algorithm - * The algorithm for the digest. This algorithm must be supported - * by the MessageDigest class. - * @param data - * the data to digest with the given algorithm - * @return The digested plain text String represented as Hex digits. - * @throws java.security.NoSuchAlgorithmException - * if the desired algorithm is not supported by the - * MessageDigest class. - */ - public static String digest(String algorithm, byte[] data) throws NoSuchAlgorithmException { - - MessageDigest md = MessageDigest.getInstance(algorithm); - byte[] digest = md.digest(data); - StringBuilder res = new StringBuilder(digest.length * 2); - for (byte b : digest) { - res.append(hexTable[(b >> 4) & 15]); - res.append(hexTable[b & 15]); - } - return res.toString(); - } - - /** - * returns an array of strings decomposed of the original string, split at - * every occurrence of 'ch'. if 2 'ch' follow each other with no - * intermediate characters, empty "" entries are avoided. - * - * @param str - * the string to decompose - * @param ch - * the character to use a split pattern - * @return an array of strings - */ - public static String[] explode(String str, int ch) { - return explode(str, ch, false); - } - - /** - * returns an array of strings decomposed of the original string, split at - * every occurrence of 'ch'. - * - * @param str - * the string to decompose - * @param ch - * the character to use a split pattern - * @param respectEmpty - * if true, empty elements are generated - * @return an array of strings - */ - public static String[] explode(String str, int ch, boolean respectEmpty) { - if (str == null || str.length() == 0) { - return new String[0]; - } - - ArrayList strings = new ArrayList(); - int pos; - int lastpos = 0; - - // add snipples - while ((pos = str.indexOf(ch, lastpos)) >= 0) { - if (pos - lastpos > 0 || respectEmpty) { - strings.add(str.substring(lastpos, pos)); - } - lastpos = pos + 1; - } - // add rest - if (lastpos < str.length()) { - strings.add(str.substring(lastpos)); - } else if (respectEmpty && lastpos == str.length()) { - strings.add(""); - } - - // return string array - return strings.toArray(new String[strings.size()]); - } - - /** - * Concatenates all strings in the string array using the specified - * delimiter. - * - * @param arr - * @param delim - * @return the concatenated string - */ - public static String implode(String[] arr, String delim) { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < arr.length; i++) { - if (i > 0) { - buf.append(delim); - } - buf.append(arr[i]); - } - return buf.toString(); - } - - /** - * Replaces all occurrences of oldString in text - * with newString. - * - * @param text - * @param oldString - * old substring to be replaced with newString - * @param newString - * new substring to replace occurrences of oldString - * @return a string - */ - public static String replace(String text, String oldString, String newString) { - if (text == null || oldString == null || newString == null) { - throw new IllegalArgumentException("null argument"); - } - int pos = text.indexOf(oldString); - if (pos == -1) { - return text; - } - int lastPos = 0; - StringBuilder sb = new StringBuilder(text.length()); - while (pos != -1) { - sb.append(text.substring(lastPos, pos)); - sb.append(newString); - lastPos = pos + oldString.length(); - pos = text.indexOf(oldString, lastPos); - } - if (lastPos < text.length()) { - sb.append(text.substring(lastPos)); - } - return sb.toString(); - } - - /** - * Replaces XML characters in the given string that might need escaping as - * XML text or attribute - * - * @param text - * text to be escaped - * @return a string - */ - public static String encodeIllegalXMLCharacters(String text) { - return encodeMarkupCharacters(text, false); - } - - /** - * Replaces HTML characters in the given string that might need escaping as - * HTML text or attribute - * - * @param text - * text to be escaped - * @return a string - */ - public static String encodeIllegalHTMLCharacters(String text) { - return encodeMarkupCharacters(text, true); - } - - private static String encodeMarkupCharacters(String text, boolean isHtml) { - if (text == null) { - throw new IllegalArgumentException("null argument"); - } - StringBuilder buf = null; - int length = text.length(); - int pos = 0; - for (int i = 0; i < length; i++) { - int ch = text.charAt(i); - switch (ch) { - case '<': - case '>': - case '&': - case '"': - case '\'': - if (buf == null) { - buf = new StringBuilder(); - } - if (i > 0) { - buf.append(text.substring(pos, i)); - } - pos = i + 1; - break; - default: - continue; - } - if (ch == '<') { - buf.append("<"); - } else if (ch == '>') { - buf.append(">"); - } else if (ch == '&') { - buf.append("&"); - } else if (ch == '"') { - buf.append("""); - } else if (ch == '\'') { - buf.append(isHtml ? "'" : "'"); - } - } - if (buf == null) { - return text; - } else { - if (pos < length) { - buf.append(text.substring(pos)); - } - return buf.toString(); - } - } - - /** - * The list of characters that are not encoded by the escape() - * and unescape() METHODS. They contains the characters as - * defined 'unreserved' in section 2.3 of the RFC 2396 'URI generic syntax': - *

- * - *

-	 * unreserved  = alphanum | mark
-	 * mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
-	 * 
- */ - public static BitSet URISave; - - /** - * Same as {@link #URISave} but also contains the '/' - */ - public static BitSet URISaveEx; - - static { - URISave = new BitSet(256); - int i; - for (i = 'a'; i <= 'z'; i++) { - URISave.set(i); - } - for (i = 'A'; i <= 'Z'; i++) { - URISave.set(i); - } - for (i = '0'; i <= '9'; i++) { - URISave.set(i); - } - URISave.set('-'); - URISave.set('_'); - URISave.set('.'); - URISave.set('!'); - URISave.set('~'); - URISave.set('*'); - URISave.set('\''); - URISave.set('('); - URISave.set(')'); - - URISaveEx = (BitSet) URISave.clone(); - URISaveEx.set('/'); - } - - /** - * Does an URL encoding of the string using the - * escape character. The characters that don't need encoding - * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax' - * RFC 2396, but without the escape character. - * - * @param string - * the string to encode. - * @param escape - * the escape character. - * @return the escaped string - * @throws NullPointerException - * if string is null. - */ - public static String escape(String string, char escape) { - return escape(string, escape, false); - } - - /** - * Does an URL encoding of the string using the - * escape character. The characters that don't need encoding - * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax' - * RFC 2396, but without the escape character. If isPath is - * true, additionally the slash '/' is ignored, too. - * - * @param string - * the string to encode. - * @param escape - * the escape character. - * @param isPath - * if true, the string is treated as path - * @return the escaped string - * @throws NullPointerException - * if string is null. - */ - public static String escape(String string, char escape, boolean isPath) { - try { - BitSet validChars = isPath ? URISaveEx : URISave; - byte[] bytes = string.getBytes("utf-8"); - StringBuilder out = new StringBuilder(bytes.length); - for (byte aByte : bytes) { - int c = aByte & 0xff; - if (validChars.get(c) && c != escape) { - out.append((char) c); - } else { - out.append(escape); - out.append(hexTable[(c >> 4) & 0x0f]); - out.append(hexTable[(c) & 0x0f]); - } - } - return out.toString(); - } catch (UnsupportedEncodingException e) { - throw new InternalError(e.toString()); - } - } - - /** - * Does a URL encoding of the string. The characters that don't - * need encoding are those defined 'unreserved' in section 2.3 of the 'URI - * generic syntax' RFC 2396. - * - * @param string - * the string to encode - * @return the escaped string - * @throws NullPointerException - * if string is null. - */ - public static String escape(String string) { - return escape(string, '%'); - } - - /** - * Does a URL encoding of the path. The characters that don't - * need encoding are those defined 'unreserved' in section 2.3 of the 'URI - * generic syntax' RFC 2396. In contrast to the {@link #escape(String)} - * method, not the entire path string is escaped, but every individual part - * (i.e. the slashes are not escaped). - * - * @param path - * the path to encode - * @return the escaped path - * @throws NullPointerException - * if path is null. - */ - public static String escapePath(String path) { - return escape(path, '%', true); - } - - /** - * Does a URL decoding of the string using the - * escape character. Please note that in opposite to the - * {@link java.net.URLDecoder} it does not transform the + into spaces. - * - * @param string - * the string to decode - * @param escape - * the escape character - * @return the decoded string - * @throws NullPointerException - * if string is null. - * @throws IllegalArgumentException - * if the 2 characters following the escape character do not - * represent a hex-number or if not enough characters follow an - * escape character - */ - public static String unescape(String string, char escape) { - try { - byte[] utf8 = string.getBytes("utf-8"); - - // Check whether escape occurs at invalid position - if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) - || (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) { - throw new IllegalArgumentException("Premature end of escape sequence at end of input"); - } - - ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length); - for (int k = 0; k < utf8.length; k++) { - byte b = utf8[k]; - if (b == escape) { - out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k])); - } else { - out.write(b); - } - } - - return new String(out.toByteArray(), "utf-8"); - } catch (UnsupportedEncodingException e) { - throw new InternalError(e.toString()); - } - } - - /** - * Does a URL decoding of the string. Please note that in - * opposite to the {@link java.net.URLDecoder} it does not transform the + - * into spaces. - * - * @param string - * the string to decode - * @return the decoded string - * @throws NullPointerException - * if string is null. - * @throws ArrayIndexOutOfBoundsException - * if not enough character follow an escape character - * @throws IllegalArgumentException - * if the 2 characters following the escape character do not - * represent a hex-number. - */ - public static String unescape(String string) { - return unescape(string, '%'); - } - - /** - * Escapes all illegal JCR name characters of a string. The encoding is - * loosely modeled after URI encoding, but only encodes the characters it - * absolutely needs to in order to make the resulting string a valid JCR - * name. Use {@link #unescapeIllegalJcrChars(String)} for decoding. - *

- * QName EBNF:
- *

simplename ::= onecharsimplename | twocharsimplename | - * threeormorecharname onecharsimplename ::= (* Any Unicode character - * except: '.', '/', ':', '[', ']', '*', '|' or any whitespace character *) - * twocharsimplename ::= '.' onecharsimplename | onecharsimplename '.' | - * onecharsimplename onecharsimplename threeormorecharname ::= nonspace - * string nonspace string ::= char | string char char ::= nonspace | ' ' - * nonspace ::= (* Any Unicode character except: '/', ':', '[', ']', '*', - * '|' or any whitespace character *) - * - * @param name - * the name to escape - * @return the escaped name - */ - public static String escapeIllegalJcrChars(String name) { - return escapeIllegalChars(name, "%/:[]*|\t\r\n"); - } - - /** - * Escapes all illegal JCR 1.0 name characters of a string. Use - * {@link #unescapeIllegalJcrChars(String)} for decoding. - *

- * QName EBNF:
- *

simplename ::= onecharsimplename | twocharsimplename | - * threeormorecharname onecharsimplename ::= (* Any Unicode character - * except: '.', '/', ':', '[', ']', '*', ''', '"', '|' or any whitespace - * character *) twocharsimplename ::= '.' onecharsimplename | - * onecharsimplename '.' | onecharsimplename onecharsimplename - * threeormorecharname ::= nonspace string nonspace string ::= char | string - * char char ::= nonspace | ' ' nonspace ::= (* Any Unicode character - * except: '/', ':', '[', ']', '*', ''', '"', '|' or any whitespace - * character *) - * - * @since Apache Jackrabbit 2.3.2 and 2.2.10 - * @see
JCR-3128 - * @param name - * the name to escape - * @return the escaped name - */ - public static String escapeIllegalJcr10Chars(String name) { - return escapeIllegalChars(name, "%/:[]*'\"|\t\r\n"); - } - - private static String escapeIllegalChars(String name, String illegal) { - StringBuilder buffer = new StringBuilder(name.length() * 2); - for (int i = 0; i < name.length(); i++) { - char ch = name.charAt(i); - if (illegal.indexOf(ch) != -1 || (ch == '.' && name.length() < 3) - || (ch == ' ' && (i == 0 || i == name.length() - 1))) { - buffer.append('%'); - buffer.append(Character.toUpperCase(Character.forDigit(ch / 16, 16))); - buffer.append(Character.toUpperCase(Character.forDigit(ch % 16, 16))); - } else { - buffer.append(ch); - } - } - return buffer.toString(); - } - - /** - * Escapes illegal XPath search characters at the end of a string. - *

- * Example:
- * A search string like 'test?' will run into a ParseException documented in - * http://issues.apache.org/jira/browse/JCR-1248 - * - * @param s - * the string to encode - * @return the escaped string - */ - public static String escapeIllegalXpathSearchChars(String s) { - StringBuilder sb = new StringBuilder(); - sb.append(s.substring(0, (s.length() - 1))); - char c = s.charAt(s.length() - 1); - // NOTE: keep this in sync with _ESCAPED_CHAR below! - if (c == '!' || c == '(' || c == ':' || c == '^' || c == '[' || c == ']' || c == '{' || c == '}' || c == '?') { - sb.append('\\'); - } - sb.append(c); - return sb.toString(); - } - - /** - * Unescapes previously escaped jcr chars. - *

- * Please note, that this does not exactly the same as the url related - * {@link #unescape(String)}, since it handles the byte-encoding - * differently. - * - * @param name - * the name to unescape - * @return the unescaped name - */ - public static String unescapeIllegalJcrChars(String name) { - StringBuilder buffer = new StringBuilder(name.length()); - int i = name.indexOf('%'); - while (i > -1 && i + 2 < name.length()) { - buffer.append(name.toCharArray(), 0, i); - int a = Character.digit(name.charAt(i + 1), 16); - int b = Character.digit(name.charAt(i + 2), 16); - if (a > -1 && b > -1) { - buffer.append((char) (a * 16 + b)); - name = name.substring(i + 3); - } else { - buffer.append('%'); - name = name.substring(i + 1); - } - i = name.indexOf('%'); - } - buffer.append(name); - return buffer.toString(); - } - - /** - * Returns the name part of the path. If the given path is already a name - * (i.e. contains no slashes) it is returned. - * - * @param path - * the path - * @return the name part or null if path is - * null. - */ - public static String getName(String path) { - return getName(path, '/'); - } - - /** - * Returns the name part of the path, delimited by the given - * delim. If the given path is already a name (i.e. contains no - * delim characters) it is returned. - * - * @param path - * the path - * @param delim - * the delimiter - * @return the name part or null if path is - * null. - */ - public static String getName(String path, char delim) { - return path == null ? null : path.substring(path.lastIndexOf(delim) + 1); - } - - /** - * Same as {@link #getName(String)} but adding the possibility to pass paths - * that end with a trailing '/' - * - * @see #getName(String) - */ - public static String getName(String path, boolean ignoreTrailingSlash) { - if (ignoreTrailingSlash && path != null && path.endsWith("/") && path.length() > 1) { - path = path.substring(0, path.length() - 1); - } - return getName(path); - } - - /** - * Returns the namespace prefix of the given qname. If the - * prefix is missing, an empty string is returned. Please note, that this - * method does not validate the name or prefix. - *

- * the qname has the format: qname := [prefix ':'] local; - * - * @param qname - * a qualified name - * @return the prefix of the name or "". - * - * @see #getLocalName(String) - * - * @throws NullPointerException - * if qname is null - */ - public static String getNamespacePrefix(String qname) { - int pos = qname.indexOf(':'); - return pos >= 0 ? qname.substring(0, pos) : ""; - } - - /** - * Returns the local name of the given qname. Please note, that - * this method does not validate the name. - *

- * the qname has the format: qname := [prefix ':'] local; - * - * @param qname - * a qualified name - * @return the localname - * - * @see #getNamespacePrefix(String) - * - * @throws NullPointerException - * if qname is null - */ - public static String getLocalName(String qname) { - int pos = qname.indexOf(':'); - return pos >= 0 ? qname.substring(pos + 1) : qname; - } - - /** - * Determines, if two paths denote hierarchical siblins. - * - * @param p1 - * first path - * @param p2 - * second path - * @return true if on same level, false otherwise - */ - public static boolean isSibling(String p1, String p2) { - int pos1 = p1.lastIndexOf('/'); - int pos2 = p2.lastIndexOf('/'); - return (pos1 == pos2 && pos1 >= 0 && p1.regionMatches(0, p2, 0, pos1)); - } - - /** - * Determines if the descendant path is hierarchical a - * descendant of path. - * - * @param path - * the current path - * @param descendant - * the potential descendant - * @return true if the descendant is a descendant; - * false otherwise. - */ - public static boolean isDescendant(String path, String descendant) { - String pattern = path.endsWith("/") ? path : path + "/"; - return !pattern.equals(descendant) && descendant.startsWith(pattern); - } - - /** - * Determines if the descendant path is hierarchical a - * descendant of path or equal to it. - * - * @param path - * the path to check - * @param descendant - * the potential descendant - * @return true if the descendant is a descendant - * or equal; false otherwise. - */ - public static boolean isDescendantOrEqual(String path, String descendant) { - if (path.equals(descendant)) { - return true; - } else { - String pattern = path.endsWith("/") ? path : path + "/"; - return descendant.startsWith(pattern); - } - } - - /** - * Returns the nth relative parent of the path, where n=level. - *

- * Example:
- * - * Text.getRelativeParent("/foo/bar/test", 1) == "/foo/bar" - * - * - * @param path - * the path of the page - * @param level - * the level of the parent - */ - public static String getRelativeParent(String path, int level) { - int idx = path.length(); - while (level > 0) { - idx = path.lastIndexOf('/', idx - 1); - if (idx < 0) { - return ""; - } - level--; - } - return (idx == 0) ? "/" : path.substring(0, idx); - } - - /** - * Same as {@link #getRelativeParent(String, int)} but adding the - * possibility to pass paths that end with a trailing '/' - * - * @see #getRelativeParent(String, int) - */ - public static String getRelativeParent(String path, int level, boolean ignoreTrailingSlash) { - if (ignoreTrailingSlash && path.endsWith("/") && path.length() > 1) { - path = path.substring(0, path.length() - 1); - } - return getRelativeParent(path, level); - } - - /** - * Returns the nth absolute parent of the path, where n=level. - *

- * Example:
- * - * Text.getAbsoluteParent("/foo/bar/test", 1) == "/foo/bar" - * - * - * @param path - * the path of the page - * @param level - * the level of the parent - */ - public static String getAbsoluteParent(String path, int level) { - int idx = 0; - int len = path.length(); - while (level >= 0 && idx < len) { - idx = path.indexOf('/', idx + 1); - if (idx < 0) { - idx = len; - } - level--; - } - return level >= 0 ? "" : path.substring(0, idx); - } - - /** - * Performs variable replacement on the given string value. Each - * ${...} sequence within the given value is replaced with the - * value of the named parser variable. If a variable is not found in the - * properties an IllegalArgumentException is thrown unless - * ignoreMissing is true. In the later case, the - * missing variable is replaced by the empty string. - * - * @param value - * the original value - * @param ignoreMissing - * if true, missing variables are replaced by the - * empty string. - * @return value after variable replacements - * @throws IllegalArgumentException - * if the replacement of a referenced variable is not found - */ - public static String replaceVariables(Properties variables, String value, boolean ignoreMissing) - throws IllegalArgumentException { - StringBuilder result = new StringBuilder(); - - // Value: - // +--+-+--------+-+-----------------+ - // | |p|--> |q|--> | - // +--+-+--------+-+-----------------+ - int p = 0, q = value.indexOf("${"); // Find first ${ - while (q != -1) { - result.append(value.substring(p, q)); // Text before ${ - p = q; - q = value.indexOf("}", q + 2); // Find } - if (q != -1) { - String variable = value.substring(p + 2, q); - String replacement = variables.getProperty(variable); - if (replacement == null) { - if (ignoreMissing) { - replacement = ""; - } else { - throw new IllegalArgumentException("Replacement not found for ${" + variable + "}."); - } - } - result.append(replacement); - p = q + 1; - q = value.indexOf("${", p); // Find next ${ - } - } - result.append(value.substring(p, value.length())); // Trailing text - - return result.toString(); - } - - private static byte decodeDigit(byte b) { - if (b >= 0x30 && b <= 0x39) { - return (byte) (b - 0x30); - } else if (b >= 0x41 && b <= 0x46) { - return (byte) (b - 0x37); - } else if (b >= 0x61 && b <= 0x66) { - return (byte) (b - 0x57); - } else { - throw new IllegalArgumentException("Escape sequence is not hexadecimal: " + (char) b); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/WorkspaceFileStore.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/WorkspaceFileStore.java deleted file mode 100644 index ce4205a97..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/WorkspaceFileStore.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.argeo.jcr.fs; - -import java.io.IOException; -import java.nio.file.FileStore; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileStoreAttributeView; -import java.util.Arrays; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Workspace; - -import org.argeo.api.acr.fs.AbstractFsStore; -import org.argeo.jcr.JcrUtils; - -/** A {@link FileStore} implementation based on JCR {@link Workspace}. */ -public class WorkspaceFileStore extends AbstractFsStore { - private final String mountPath; - private final Workspace workspace; - private final String workspaceName; - private final int mountDepth; - - public WorkspaceFileStore(String mountPath, Workspace workspace) { - if ("/".equals(mountPath) || "".equals(mountPath)) - throw new IllegalArgumentException( - "Mount path '" + mountPath + "' is unsupported, use null for the base file store"); - if (mountPath != null && !mountPath.startsWith(JcrPath.separator)) - throw new IllegalArgumentException("Mount path '" + mountPath + "' cannot end with /"); - if (mountPath != null && mountPath.endsWith(JcrPath.separator)) - throw new IllegalArgumentException("Mount path '" + mountPath + "' cannot end with /"); - this.mountPath = mountPath; - if (mountPath == null) - mountDepth = 0; - else { - mountDepth = mountPath.split(JcrPath.separator).length - 1; - } - this.workspace = workspace; - this.workspaceName = workspace.getName(); - } - - public void close() { - JcrUtils.logoutQuietly(workspace.getSession()); - } - - @Override - public String name() { - return workspace.getName(); - } - - @Override - public String type() { - return "workspace"; - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - public long getTotalSpace() throws IOException { - return 0; - } - - @Override - public long getUsableSpace() throws IOException { - return 0; - } - - @Override - public long getUnallocatedSpace() throws IOException { - return 0; - } - - @Override - public boolean supportsFileAttributeView(Class type) { - return false; - } - - @Override - public boolean supportsFileAttributeView(String name) { - return false; - } - - @Override - public V getFileStoreAttributeView(Class type) { - return null; - } - - @Override - public Object getAttribute(String attribute) throws IOException { - return workspace.getSession().getRepository().getDescriptor(attribute); - } - - public Workspace getWorkspace() { - return workspace; - } - - public String toFsPath(Node node) throws RepositoryException { - String nodeWorkspaceName = node.getSession().getWorkspace().getName(); - if (!nodeWorkspaceName.equals(workspace.getName())) - throw new IllegalArgumentException("Icompatible " + node + " from workspace '" + nodeWorkspaceName - + "' in file store '" + workspace.getName() + "'"); - return mountPath == null ? node.getPath() : mountPath + node.getPath(); - } - - public boolean isBase() { - return mountPath == null; - } - - Node toNode(String[] fullPath) throws RepositoryException { - String jcrPath = toJcrPath(fullPath); - Session session = workspace.getSession(); - if (!session.itemExists(jcrPath)) - return null; - Node node = session.getNode(jcrPath); - return node; - } - - String toJcrPath(String fsPath) { - if (fsPath.length() == 1) - return toJcrPath((String[]) null);// root - String[] arr = fsPath.substring(1).split("/"); -// if (arr.length == 0 || (arr.length == 1 && arr[0].equals(""))) -// return toJcrPath((String[]) null);// root -// else - return toJcrPath(arr); - } - - private String toJcrPath(String[] path) { - if (path == null) - return "/"; - if (path.length < mountDepth) - throw new IllegalArgumentException( - "Path " + Arrays.asList(path) + " is no compatible with mount " + mountPath); - - if (!isBase()) { - // check mount compatibility - StringBuilder mount = new StringBuilder(); - mount.append('/'); - for (int i = 0; i < mountDepth; i++) { - if (i != 0) - mount.append('/'); - mount.append(Text.escapeIllegalJcrChars(path[i])); - } - if (!mountPath.equals(mount.toString())) - throw new IllegalArgumentException( - "Path " + Arrays.asList(path) + " is no compatible with mount " + mountPath); - } - - StringBuilder sb = new StringBuilder(); - sb.append('/'); - for (int i = mountDepth; i < path.length; i++) { - if (i != mountDepth) - sb.append('/'); - sb.append(Text.escapeIllegalJcrChars(path[i])); - } - return sb.toString(); - } - - public String getMountPath() { - return mountPath; - } - - public String getWorkspaceName() { - return workspaceName; - } - - public int getMountDepth() { - return mountDepth; - } - - @Override - public int hashCode() { - return workspaceName.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof WorkspaceFileStore)) - return false; - WorkspaceFileStore other = (WorkspaceFileStore) obj; - return workspaceName.equals(other.workspaceName); - } - - @Override - public String toString() { - return "WorkspaceFileStore " + workspaceName; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/package-info.java deleted file mode 100644 index 0cdfdaf43..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/fs/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Java NIO file system implementation based on plain JCR. */ -package org.argeo.jcr.fs; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/jcrx.cnd b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/jcrx.cnd deleted file mode 100644 index 3eb0e7a3d..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/jcrx.cnd +++ /dev/null @@ -1,16 +0,0 @@ -// -// JCR EXTENSIONS -// - - -[jcrx:xmlvalue] -- * -+ jcr:xmltext (jcrx:xmltext) = jcrx:xmltext - -[jcrx:xmltext] - - jcr:xmlcharacters (STRING) mandatory - -[jcrx:csum] -mixin - - jcrx:sum (STRING) * - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/package-info.java deleted file mode 100644 index 1837749f1..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic JCR utilities. */ -package org.argeo.jcr; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/AbstractUrlProxy.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/AbstractUrlProxy.java deleted file mode 100644 index 0177636f8..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/AbstractUrlProxy.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.argeo.jcr.proxy; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; - -/** Base class for URL based proxys. */ -public abstract class AbstractUrlProxy implements ResourceProxy { - private final static CmsLog log = CmsLog.getLog(AbstractUrlProxy.class); - - private Repository jcrRepository; - private Session jcrAdminSession; - private String proxyWorkspace = "proxy"; - - protected abstract Node retrieve(Session session, String path); - - void init() { - try { - jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository, proxyWorkspace); - beforeInitSessionSave(jcrAdminSession); - if (jcrAdminSession.hasPendingChanges()) - jcrAdminSession.save(); - } catch (RepositoryException e) { - JcrUtils.discardQuietly(jcrAdminSession); - throw new JcrException("Cannot initialize URL proxy", e); - } - } - - /** - * Called before the (admin) session is saved at the end of the initialization. - * Does nothing by default, to be overridden. - */ - protected void beforeInitSessionSave(Session session) throws RepositoryException { - } - - void destroy() { - JcrUtils.logoutQuietly(jcrAdminSession); - } - - /** - * Called before the (admin) session is logged out when resources are released. - * Does nothing by default, to be overridden. - */ - protected void beforeDestroySessionLogout() throws RepositoryException { - } - - public Node proxy(String path) { - // we open a JCR session with client credentials in order not to use the - // admin session in multiple thread or make it a bottleneck. - Node nodeAdmin = null; - Node nodeClient = null; - Session clientSession = null; - try { - clientSession = jcrRepository.login(proxyWorkspace); - if (!clientSession.itemExists(path) || shouldUpdate(clientSession, path)) { - nodeAdmin = retrieveAndSave(path); - if (nodeAdmin != null) - nodeClient = clientSession.getNode(path); - } else - nodeClient = clientSession.getNode(path); - return nodeClient; - } catch (RepositoryException e) { - throw new JcrException("Cannot proxy " + path, e); - } finally { - if (nodeClient == null) - JcrUtils.logoutQuietly(clientSession); - } - } - - protected synchronized Node retrieveAndSave(String path) { - try { - Node node = retrieve(jcrAdminSession, path); - if (node == null) - return null; - jcrAdminSession.save(); - return node; - } catch (RepositoryException e) { - JcrUtils.discardQuietly(jcrAdminSession); - throw new JcrException("Cannot retrieve and save " + path, e); - } finally { - notifyAll(); - } - } - - /** Session is not saved */ - protected synchronized Node proxyUrl(Session session, String remoteUrl, String path) throws RepositoryException { - Node node = null; - if (session.itemExists(path)) { - // throw new ArgeoJcrException("Node " + path + " already exists"); - } - try (InputStream in = new URL(remoteUrl).openStream()) { - // URL u = new URL(remoteUrl); - // in = u.openStream(); - node = importFile(session, path, in); - } catch (IOException e) { - if (log.isDebugEnabled()) { - log.debug("Cannot read " + remoteUrl + ", skipping... " + e.getMessage()); - // log.trace("Cannot read because of ", e); - } - JcrUtils.discardQuietly(session); - // } finally { - // IOUtils.closeQuietly(in); - } - return node; - } - - protected synchronized Node importFile(Session session, String path, InputStream in) throws RepositoryException { - Binary binary = null; - try { - Node content = null; - Node node = null; - if (!session.itemExists(path)) { - node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE, NodeType.NT_FOLDER, false); - content = node.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED); - } else { - node = session.getNode(path); - content = node.getNode(Node.JCR_CONTENT); - } - binary = session.getValueFactory().createBinary(in); - content.setProperty(Property.JCR_DATA, binary); - JcrUtils.updateLastModifiedAndParents(node, null, true); - return node; - } finally { - JcrUtils.closeQuietly(binary); - } - } - - /** Whether the file should be updated. */ - protected Boolean shouldUpdate(Session clientSession, String nodePath) { - return false; - } - - public void setJcrRepository(Repository jcrRepository) { - this.jcrRepository = jcrRepository; - } - - public void setProxyWorkspace(String localWorkspace) { - this.proxyWorkspace = localWorkspace; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxy.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxy.java deleted file mode 100644 index 84eea1f31..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxy.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.argeo.jcr.proxy; - -import javax.jcr.Node; - -/** A proxy which nows how to resolve and synchronize relative URLs */ -public interface ResourceProxy { - /** - * Proxy the file referenced by this relative path in the underlying - * repository. A new session is created by each call, so the underlying - * session of the returned node must be closed by the caller. - * - * @return the proxied Node, null if the resource was not found - * (e.g. HTTP 404) - */ - public Node proxy(String relativePath); -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxyServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxyServlet.java deleted file mode 100644 index a8e00df60..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/ResourceProxyServlet.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.argeo.jcr.proxy; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.argeo.jcr.JcrException; -import org.argeo.api.cms.CmsLog; -import org.argeo.jcr.Bin; -import org.argeo.jcr.JcrUtils; - -/** Wraps a proxy via HTTP */ -public class ResourceProxyServlet extends HttpServlet { - private static final long serialVersionUID = -8886549549223155801L; - - private final static CmsLog log = CmsLog - .getLog(ResourceProxyServlet.class); - - private ResourceProxy proxy; - - private String contentTypeCharset = "UTF-8"; - - @Override - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - String path = request.getPathInfo(); - - if (log.isTraceEnabled()) { - log.trace("path=" + path); - log.trace("UserPrincipal = " + request.getUserPrincipal().getName()); - log.trace("SessionID = " + request.getSession(false).getId()); - log.trace("ContextPath = " + request.getContextPath()); - log.trace("ServletPath = " + request.getServletPath()); - log.trace("PathInfo = " + request.getPathInfo()); - log.trace("Method = " + request.getMethod()); - log.trace("User-Agent = " + request.getHeader("User-Agent")); - } - - Node node = null; - try { - node = proxy.proxy(path); - if (node == null) - response.sendError(404); - else - processResponse(node, response); - } finally { - if (node != null) - try { - JcrUtils.logoutQuietly(node.getSession()); - } catch (RepositoryException e) { - // silent - } - } - - } - - /** Retrieve the content of the node. */ - protected void processResponse(Node node, HttpServletResponse response) { -// Binary binary = null; -// InputStream in = null; - try(Bin binary = new Bin( node.getNode(Property.JCR_CONTENT) - .getProperty(Property.JCR_DATA));InputStream in = binary.getStream()) { - String fileName = node.getName(); - String ext = FilenameUtils.getExtension(fileName); - - // TODO use a more generic / standard approach - // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml - String contentType; - if ("xml".equals(ext)) - contentType = "text/xml;charset=" + contentTypeCharset; - else if ("jar".equals(ext)) - contentType = "application/java-archive"; - else if ("zip".equals(ext)) - contentType = "application/zip"; - else if ("gz".equals(ext)) - contentType = "application/x-gzip"; - else if ("bz2".equals(ext)) - contentType = "application/x-bzip2"; - else if ("tar".equals(ext)) - contentType = "application/x-tar"; - else if ("rpm".equals(ext)) - contentType = "application/x-redhat-package-manager"; - else - contentType = "application/octet-stream"; - contentType = contentType + ";name=\"" + fileName + "\""; - response.setHeader("Content-Disposition", "attachment; filename=\"" - + fileName + "\""); - response.setHeader("Expires", "0"); - response.setHeader("Cache-Control", "no-cache, must-revalidate"); - response.setHeader("Pragma", "no-cache"); - - response.setContentType(contentType); - - IOUtils.copy(in, response.getOutputStream()); - } catch (RepositoryException e) { - throw new JcrException("Cannot download " + node, e); - } catch (IOException e) { - throw new RuntimeException("Cannot download " + node, e); - } - } - - public void setProxy(ResourceProxy resourceProxy) { - this.proxy = resourceProxy; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/package-info.java deleted file mode 100644 index a578c456e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/proxy/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Components to build proxys based on JCR. */ -package org.argeo.jcr.proxy; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java deleted file mode 100644 index 2adb6a97e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java +++ /dev/null @@ -1,186 +0,0 @@ -package org.argeo.jcr.xml; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.nodetype.NodeType; - -import org.argeo.jcr.Jcr; - -/** Utilities around JCR and XML. */ -public class JcrXmlUtils { - /** - * Convenience method calling {@link #toXmlElements(Writer, Node, boolean)} with - * false. - */ - public static void toXmlElements(Writer writer, Node node) throws RepositoryException, IOException { - toXmlElements(writer, node, null, false, false, false); - } - - /** - * Write JCR properties as XML elements in a tree structure whose elements are - * named by node primary type. - * - * @param writer the writer to use - * @param node the subtree - * @param depth maximal depth, or if null the whole - * subtree. It must be positive, with depth 0 - * describing just the node without its children. - * @param withMetadata whether to write the primary type and mixins as - * elements - * @param withPrefix whether to keep the namespace prefixes - * @param propertiesAsElements whether single properties should be written as - * elements rather than attributes. If - * false, multiple properties will be - * skipped. - */ - public static void toXmlElements(Writer writer, Node node, Integer depth, boolean withMetadata, boolean withPrefix, - boolean propertiesAsElements) throws RepositoryException, IOException { - if (depth != null && depth < 0) - throw new IllegalArgumentException("Depth " + depth + " is negative."); - - if (node.getName().equals(Jcr.JCR_XMLTEXT)) { - writer.write(node.getProperty(Jcr.JCR_XMLCHARACTERS).getString()); - return; - } - - if (!propertiesAsElements) { - Map attrs = new TreeMap<>(); - PropertyIterator pit = node.getProperties(); - properties: while (pit.hasNext()) { - Property p = pit.nextProperty(); - if (!p.isMultiple()) { - String pName = p.getName(); - if (!withMetadata && (pName.equals(Jcr.JCR_PRIMARY_TYPE) || pName.equals(Jcr.JCR_UUID) - || pName.equals(Jcr.JCR_CREATED) || pName.equals(Jcr.JCR_CREATED_BY) - || pName.equals(Jcr.JCR_LAST_MODIFIED) || pName.equals(Jcr.JCR_LAST_MODIFIED_BY))) - continue properties; - attrs.put(withPrefix(p.getName(), withPrefix), p.getString()); - } - } - if (withMetadata && node.hasProperty(Property.JCR_UUID)) - attrs.put("id", "urn:uuid:" + node.getProperty(Property.JCR_UUID).getString()); - attrs.put(withPrefix ? Jcr.JCR_NAME : "name", node.getName()); - writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix), attrs, node.hasNodes()); - } else { - if (withMetadata && node.hasProperty(Property.JCR_UUID)) { - writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix), "id", - "urn:uuid:" + node.getProperty(Property.JCR_UUID).getString()); - } else { - writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix)); - } - // name - writeStart(writer, withPrefix ? Jcr.JCR_NAME : "name"); - writer.append(node.getName()); - writeEnd(writer, withPrefix ? Jcr.JCR_NAME : "name"); - } - - // mixins - if (withMetadata) { - for (NodeType mixin : node.getMixinNodeTypes()) { - writeStart(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes"); - writer.append(mixin.getName()); - writeEnd(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes"); - } - } - - // properties as elements - if (propertiesAsElements) { - PropertyIterator pit = node.getProperties(); - properties: while (pit.hasNext()) { - Property p = pit.nextProperty(); - if (p.isMultiple()) { - for (Value value : p.getValues()) { - writeStart(writer, withPrefix(p.getName(), withPrefix)); - writer.write(value.getString()); - writeEnd(writer, withPrefix(p.getName(), withPrefix)); - } - } else { - Value value = p.getValue(); - String pName = p.getName(); - if (!withMetadata && (pName.equals(Jcr.JCR_PRIMARY_TYPE) || pName.equals(Jcr.JCR_UUID) - || pName.equals(Jcr.JCR_CREATED) || pName.equals(Jcr.JCR_CREATED_BY) - || pName.equals(Jcr.JCR_LAST_MODIFIED) || pName.equals(Jcr.JCR_LAST_MODIFIED_BY))) - continue properties; - writeStart(writer, withPrefix(p.getName(), withPrefix)); - writer.write(value.getString()); - writeEnd(writer, withPrefix(p.getName(), withPrefix)); - } - } - } - - // children - if (node.hasNodes()) { - if (depth == null || depth > 0) { - NodeIterator nit = node.getNodes(); - while (nit.hasNext()) { - toXmlElements(writer, nit.nextNode(), depth == null ? null : depth - 1, withMetadata, withPrefix, - propertiesAsElements); - } - } - writeEnd(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix)); - } - } - - private static String withPrefix(String str, boolean withPrefix) { - if (withPrefix) - return str; - int index = str.indexOf(':'); - if (index < 0) - return str; - return str.substring(index + 1); - } - - private static void writeStart(Writer writer, String tagName) throws IOException { - writer.append('<'); - writer.append(tagName); - writer.append('>'); - } - - private static void writeStart(Writer writer, String tagName, String attr, String value) throws IOException { - writer.append('<'); - writer.append(tagName); - writer.append(' '); - writer.append(attr); - writer.append("=\""); - writer.append(value); - writer.append("\">"); - } - - private static void writeStart(Writer writer, String tagName, Map attrs, boolean hasChildren) - throws IOException { - writer.append('<'); - writer.append(tagName); - for (String attr : attrs.keySet()) { - writer.append(' '); - writer.append(attr); - writer.append("=\""); - writer.append(attrs.get(attr)); - writer.append('\"'); - } - if (hasChildren) - writer.append('>'); - else - writer.append("/>"); - } - - private static void writeEnd(Writer writer, String tagName) throws IOException { - writer.append("'); - } - - /** Singleton. */ - private JcrXmlUtils() { - - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/removePrefixes.xsl b/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/removePrefixes.xsl deleted file mode 100644 index 813d06570..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/jcr/xml/removePrefixes.xsl +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/AbstractMaintenanceService.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/AbstractMaintenanceService.java deleted file mode 100644 index 977adac58..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/AbstractMaintenanceService.java +++ /dev/null @@ -1,232 +0,0 @@ -package org.argeo.maintenance; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Set; - -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.acr.spi.ProvidedRepository; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.naming.Distinguished; -import org.argeo.util.transaction.WorkTransaction; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.UserAdmin; - -/** Make sure roles and access rights are properly configured. */ -public abstract class AbstractMaintenanceService { - private final static CmsLog log = CmsLog.getLog(AbstractMaintenanceService.class); - - private Repository repository; -// private UserAdminService userAdminService; - private UserAdmin userAdmin; - private WorkTransaction userTransaction; - - private ProvidedRepository contentRepository; - - public void init() { - makeSureRolesExists(getRequiredRoles()); - configureStandardRoles(); - - Set workspaceNames = getWorkspaceNames(); - if (workspaceNames == null || workspaceNames.isEmpty()) { - configureJcr(repository, null); - } else { - for (String workspaceName : workspaceNames) - configureJcr(repository, workspaceName); - } - } - - /** Configures a workspace. */ - protected void configureJcr(Repository repository, String workspaceName) { - Session adminSession; - try { - adminSession = CmsJcrUtils.openDataAdminSession(repository, workspaceName); - } catch (RuntimeException e1) { - if (e1.getCause() != null && e1.getCause() instanceof NoSuchWorkspaceException) { - Session defaultAdminSession = CmsJcrUtils.openDataAdminSession(repository, null); - try { - defaultAdminSession.getWorkspace().createWorkspace(workspaceName); - log.info("Created JCR workspace " + workspaceName); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot create workspace " + workspaceName, e); - } finally { - Jcr.logout(defaultAdminSession); - } - adminSession = CmsJcrUtils.openDataAdminSession(repository, workspaceName); - } else - throw e1; - } - try { - if (prepareJcrTree(adminSession)) { - configurePrivileges(adminSession); - } - } catch (RepositoryException | IOException e) { - throw new IllegalStateException("Cannot initialise JCR data layer.", e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - - /** To be overridden. */ - protected Set getWorkspaceNames() { - return null; - } - - /** - * To be overridden in order to programmatically set relationships between - * roles. Does nothing by default. - */ - protected void configureStandardRoles() { - } - - /** - * Creates the base JCR tree structure expected for this app if necessary. - * - * Expects a clean session ({@link Session#hasPendingChanges()} should return - * false) and saves it once the changes have been done. Thus the session can be - * rolled back if an exception occurs. - * - * @return true if something as been updated - */ - public boolean prepareJcrTree(Session adminSession) throws RepositoryException, IOException { - return false; - } - - /** - * Adds app specific default privileges. - * - * Expects a clean session ({@link Session#hasPendingChanges()} should return - * false} and saves it once the changes have been done. Thus the session can be - * rolled back if an exception occurs. - * - * Warning: no check is done and corresponding privileges are always added, so - * only call this when necessary - */ - public void configurePrivileges(Session session) throws RepositoryException { - } - - /** The system roles that must be available in the system. */ - protected Set getRequiredRoles() { - return new HashSet<>(); - } - - public void destroy() { - - } - - /* - * UTILITIES - */ - - /** Create these roles as group if they don't exist. */ - protected void makeSureRolesExists(EnumSet enumSet) { - makeSureRolesExists(Distinguished.enumToDns(enumSet)); - } - - /** Create these roles as group if they don't exist. */ - protected void makeSureRolesExists(Set requiredRoles) { - if (requiredRoles == null) - return; - if (getUserAdmin() == null) { - log.warn("No user admin service available, cannot make sure that role exists"); - return; - } - for (String role : requiredRoles) { - Role systemRole = getUserAdmin().getRole(role); - if (systemRole == null) { - try { - getUserTransaction().begin(); - getUserAdmin().createRole(role, Role.GROUP); - getUserTransaction().commit(); - log.info("Created role " + role); - } catch (Exception e) { - try { - getUserTransaction().rollback(); - } catch (Exception e1) { - // silent - } - throw new IllegalStateException("Cannot create role " + role, e); - } - } - } - } - - /** Add a user or group to a group. */ - protected void addToGroup(String groupToAddDn, String groupDn) { - if (groupToAddDn.contentEquals(groupDn)) { - if (log.isTraceEnabled()) - log.trace("Ignore adding group " + groupDn + " to itself"); - return; - } - - if (getUserAdmin() == null) { - log.warn("No user admin service available, cannot add group " + groupToAddDn + " to " + groupDn); - return; - } - Group groupToAdd = (Group) getUserAdmin().getRole(groupToAddDn); - if (groupToAdd == null) - throw new IllegalArgumentException("Group " + groupToAddDn + " not found"); - Group group = (Group) getUserAdmin().getRole(groupDn); - if (group == null) - throw new IllegalArgumentException("Group " + groupDn + " not found"); - try { - getUserTransaction().begin(); - if (group.addMember(groupToAdd)) - log.info("Added " + groupToAddDn + " to " + group); - getUserTransaction().commit(); - } catch (Exception e) { - try { - getUserTransaction().rollback(); - } catch (Exception e1) { - // silent - } - throw new IllegalStateException("Cannot add " + groupToAddDn + " to " + groupDn); - } - } - - /* - * DEPENDENCY INJECTION - */ - public void setRepository(Repository repository) { - this.repository = repository; - } - -// public void setUserAdminService(UserAdminService userAdminService) { -// this.userAdminService = userAdminService; -// } - - protected WorkTransaction getUserTransaction() { - return userTransaction; - } - - protected UserAdmin getUserAdmin() { - return userAdmin; - } - - public void setUserAdmin(UserAdmin userAdmin) { - this.userAdmin = userAdmin; - } - - public void setUserTransaction(WorkTransaction userTransaction) { - this.userTransaction = userTransaction; - } - - public void setContentRepository(ProvidedRepository contentRepository) { - this.contentRepository = contentRepository; - } - - protected ProvidedRepository getContentRepository() { - return contentRepository; - } - - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/SimpleRoleRegistration.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/SimpleRoleRegistration.java deleted file mode 100644 index e65e46a4e..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/SimpleRoleRegistration.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.argeo.maintenance; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; - -import org.argeo.api.cms.CmsLog; -import org.argeo.util.transaction.WorkTransaction; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.UserAdmin; - -/** - * Register one or many roles via a user admin service. Does nothing if the role - * is already registered. - */ -public class SimpleRoleRegistration implements Runnable { - private final static CmsLog log = CmsLog.getLog(SimpleRoleRegistration.class); - - private String role; - private List roles = new ArrayList(); - private UserAdmin userAdmin; - private WorkTransaction userTransaction; - - @Override - public void run() { - try { - userTransaction.begin(); - if (role != null && !roleExists(role)) - newRole(toDn(role)); - - for (String r : roles) - if (!roleExists(r)) - newRole(toDn(r)); - userTransaction.commit(); - } catch (Exception e) { - try { - userTransaction.rollback(); - } catch (Exception e1) { - log.error("Cannot rollback", e1); - } - throw new IllegalArgumentException("Cannot add roles", e); - } - } - - private boolean roleExists(String role) { - return userAdmin.getRole(toDn(role).toString()) != null; - } - - protected void newRole(LdapName r) { - userAdmin.createRole(r.toString(), Role.GROUP); - log.info("Added role " + r + " required by application."); - } - - public void register(UserAdmin userAdminService, Map properties) { - this.userAdmin = userAdminService; - run(); - } - - protected LdapName toDn(String name) { - try { - return new LdapName("cn=" + name + ",ou=roles,ou=node"); - } catch (InvalidNameException e) { - throw new IllegalArgumentException("Badly formatted role name " + name, e); - } - } - - public void setRole(String role) { - this.role = role; - } - - public void setRoles(List roles) { - this.roles = roles; - } - - public void setUserAdmin(UserAdmin userAdminService) { - this.userAdmin = userAdminService; - } - - public void setUserTransaction(WorkTransaction userTransaction) { - this.userTransaction = userTransaction; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/BackupContentHandler.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/BackupContentHandler.java deleted file mode 100644 index ef83c1ff9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/BackupContentHandler.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.argeo.maintenance.backup; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Writer; -import java.util.Arrays; -import java.util.Base64; -import java.util.Set; -import java.util.TreeSet; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** XML handler serialising a JCR system view. */ -public class BackupContentHandler extends DefaultHandler { - final static int MAX_DEPTH = 1024; - final static String SV_NAMESPACE_URI = "http://www.jcp.org/jcr/sv/1.0"; - final static String SV_PREFIX = "sv"; - // elements - final static String NODE = "node"; - final static String PROPERTY = "property"; - final static String VALUE = "value"; - // attributes - final static String NAME = "name"; - final static String MULTIPLE = "multiple"; - final static String TYPE = "type"; - - // values - final static String BINARY = "Binary"; - final static String JCR_CONTENT = "jcr:content"; - - private Writer out; - private Session session; - private Set contentPaths = new TreeSet<>(); - - boolean prettyPrint = true; - - private final String parentPath; - -// private boolean inSystem = false; - - public BackupContentHandler(Writer out, Node node) { - super(); - this.out = out; - this.session = Jcr.getSession(node); - parentPath = Jcr.getParentPath(node); - } - - private int currentDepth = -1; - private String[] currentPath = new String[MAX_DEPTH]; - - private boolean currentPropertyIsMultiple = false; - private String currentEncoded = null; - private Base64.Encoder base64encore = Base64.getEncoder(); - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - boolean isNode; - boolean isProperty; - switch (localName) { - case NODE: - isNode = true; - isProperty = false; - break; - case PROPERTY: - isNode = false; - isProperty = true; - break; - default: - isNode = false; - isProperty = false; - } - - if (isNode) { - String nodeName = attributes.getValue(SV_NAMESPACE_URI, NAME); - currentDepth = currentDepth + 1; -// if (currentDepth >= 0) - currentPath[currentDepth] = nodeName; -// System.out.println(getCurrentPath() + " , depth=" + currentDepth); -// if ("jcr:system".equals(nodeName)) { -// inSystem = true; -// } - } -// if (inSystem) -// return; - - if (SV_NAMESPACE_URI.equals(uri)) - try { - if (prettyPrint) { - if (isNode) { - out.write(spaces()); - out.write("\n"); - out.write(spaces()); - } else if (isProperty) - out.write(spaces()); - else if (currentPropertyIsMultiple) - out.write(spaces()); - } - - out.write("<"); - out.write(SV_PREFIX + ":" + localName); - if (isProperty) - currentPropertyIsMultiple = false; // always reset - for (int i = 0; i < attributes.getLength(); i++) { - String ns = attributes.getURI(i); - if (SV_NAMESPACE_URI.equals(ns)) { - String attrName = attributes.getLocalName(i); - String attrValue = attributes.getValue(i); - out.write(" "); - out.write(SV_PREFIX + ":" + attrName); - out.write("="); - out.write("\""); - out.write(attrValue); - out.write("\""); - if (isProperty) { - if (MULTIPLE.equals(attrName)) - currentPropertyIsMultiple = Boolean.parseBoolean(attrValue); - else if (TYPE.equals(attrName)) { - if (BINARY.equals(attrValue)) { - if (JCR_CONTENT.equals(getCurrentName())) { - contentPaths.add(getCurrentJcrPath()); - } else { - Binary binary = session.getNode(getCurrentJcrPath()).getProperty(attrName) - .getBinary(); - try (InputStream in = binary.getStream()) { - currentEncoded = base64encore.encodeToString(IOUtils.toByteArray(in)); - } finally { - - } - } - } - } - } - } - } - if (isNode && currentDepth == 0) { - // out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\""); - out.write(" xmlns:" + SV_PREFIX + "=\"" + SV_NAMESPACE_URI + "\""); - } - out.write(">"); - - if (prettyPrint) - if (isNode) - out.write("\n"); - else if (isProperty && currentPropertyIsMultiple) - out.write("\n"); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - boolean isNode = localName.equals(NODE); - boolean isValue = localName.equals(VALUE); - if (prettyPrint) - if (!isValue) - try { - if (isNode || currentPropertyIsMultiple) - out.write(spaces()); - } catch (IOException e1) { - throw new RuntimeException(e1); - } - if (isNode) { -// System.out.println("endElement " + getCurrentPath() + " , depth=" + currentDepth); -// if (currentDepth > 0) - currentPath[currentDepth] = null; - currentDepth = currentDepth - 1; -// if (inSystem) { -// // System.out.println("Skip " + getCurrentPath()+" , -// // currentDepth="+currentDepth); -// if (currentDepth == 0) { -// inSystem = false; -// return; -// } -// } - } -// if (inSystem) -// return; - if (SV_NAMESPACE_URI.equals(uri)) - try { - if (isValue && currentEncoded != null) { - out.write(currentEncoded); - } - currentEncoded = null; - out.write(""); - if (prettyPrint) - if (!isValue) - out.write("\n"); - else { - if (currentPropertyIsMultiple) - out.write("\n"); - } - if (currentDepth == 0) - out.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - } - - private char[] spaces() { - char[] arr = new char[currentDepth]; - Arrays.fill(arr, ' '); - return arr; - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { -// if (inSystem) -// return; - try { - out.write(ch, start, length); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected String getCurrentName() { - assert currentDepth >= 0; -// if (currentDepth == 0) -// return "jcr:root"; - return currentPath[currentDepth]; - } - - protected String getCurrentJcrPath() { -// if (currentDepth == 0) -// return "/"; - StringBuilder sb = new StringBuilder(parentPath.equals("/") ? "" : parentPath); - for (int i = 0; i <= currentDepth; i++) { -// if (i != 0) - sb.append('/'); - sb.append(currentPath[i]); - } - return sb.toString(); - } - - public Set getContentPaths() { - return contentPaths; - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalBackup.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalBackup.java deleted file mode 100644 index 00d4be8b0..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalBackup.java +++ /dev/null @@ -1,448 +0,0 @@ -package org.argeo.maintenance.backup; - -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.net.URI; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Dictionary; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipOutputStream; - -import javax.jcr.Binary; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; - -import org.apache.commons.io.IOUtils; -import org.apache.jackrabbit.api.JackrabbitSession; -import org.apache.jackrabbit.api.JackrabbitValue; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jackrabbit.client.ClientDavexRepositoryFactory; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; - -/** - * Performs a backup of the data based only on programmatic interfaces. Useful - * for migration or live backup. Physical backups of the underlying file - * systems, databases, LDAP servers, etc. should be performed for disaster - * recovery. - */ -public class LogicalBackup implements Runnable { - private final static CmsLog log = CmsLog.getLog(LogicalBackup.class); - - public final static String WORKSPACES_BASE = "workspaces/"; - public final static String FILES_BASE = "files/"; - public final static String OSGI_BASE = "share/osgi/"; - - public final static String JCR_SYSTEM = "jcr:system"; - public final static String JCR_VERSION_STORAGE_PATH = "/jcr:system/jcr:versionStorage"; - - private final Repository repository; - private String defaultWorkspace; - private final BundleContext bundleContext; - - private final ZipOutputStream zout; - private final Path basePath; - - private ExecutorService executorService; - - private boolean performSoftwareBackup = false; - - private Map checksums = new TreeMap<>(); - - private int threadCount = 5; - - private boolean backupFailed = false; - - public LogicalBackup(BundleContext bundleContext, Repository repository, Path basePath) { - this.repository = repository; - this.zout = null; - this.basePath = basePath; - this.bundleContext = bundleContext; - } - - @Override - public void run() { - try { - log.info("Start logical backup to " + basePath); - perform(); - } catch (Exception e) { - log.error("Unexpected exception when performing logical backup", e); - throw new IllegalStateException("Logical backup failed", e); - } - - } - - public void perform() throws RepositoryException, IOException { - if (executorService != null && !executorService.isTerminated()) - throw new IllegalStateException("Another backup is running"); - executorService = Executors.newFixedThreadPool(threadCount); - long begin = System.currentTimeMillis(); - // software backup - if (bundleContext != null && performSoftwareBackup) - executorService.submit(() -> performSoftwareBackup(bundleContext)); - - // data backup - Session defaultSession = login(null); - defaultWorkspace = defaultSession.getWorkspace().getName(); - try { - String[] workspaceNames = defaultSession.getWorkspace().getAccessibleWorkspaceNames(); - workspaces: for (String workspaceName : workspaceNames) { - if ("security".equals(workspaceName)) - continue workspaces; - performDataBackup(workspaceName); - } - } finally { - JcrUtils.logoutQuietly(defaultSession); - executorService.shutdown(); - try { - executorService.awaitTermination(24, TimeUnit.HOURS); - } catch (InterruptedException e) { - // silent - throw new IllegalStateException("Backup was interrupted before completion", e); - } - } - // versions - executorService = Executors.newFixedThreadPool(threadCount); - try { - performVersionsBackup(); - } finally { - executorService.shutdown(); - try { - executorService.awaitTermination(24, TimeUnit.HOURS); - } catch (InterruptedException e) { - // silent - throw new IllegalStateException("Backup was interrupted before completion", e); - } - } - long duration = System.currentTimeMillis() - begin; - if (isBackupFailed()) - log.info("System logical backup failed after " + (duration / 60000) + "min " + (duration / 1000) + "s"); - else - log.info("System logical backup completed in " + (duration / 60000) + "min " + (duration / 1000) + "s"); - } - - protected void performDataBackup(String workspaceName) throws RepositoryException, IOException { - Session session = login(workspaceName); - try { - nodes: for (NodeIterator nit = session.getRootNode().getNodes(); nit.hasNext();) { - if (isBackupFailed()) - return; - Node nodeToExport = nit.nextNode(); - if (JCR_SYSTEM.equals(nodeToExport.getName())) - continue nodes; - String nodePath = nodeToExport.getPath(); - Future> contentPathsFuture = executorService - .submit(() -> performNodeBackup(workspaceName, nodePath)); - executorService.submit(() -> performFilesBackup(workspaceName, contentPathsFuture)); - } - } finally { - Jcr.logout(session); - } - } - - protected void performVersionsBackup() throws RepositoryException, IOException { - Session session = login(defaultWorkspace); - Node versionStorageNode = session.getNode(JCR_VERSION_STORAGE_PATH); - try { - for (NodeIterator nit = versionStorageNode.getNodes(); nit.hasNext();) { - Node nodeToExport = nit.nextNode(); - String nodePath = nodeToExport.getPath(); - if (isBackupFailed()) - return; - Future> contentPathsFuture = executorService - .submit(() -> performNodeBackup(defaultWorkspace, nodePath)); - executorService.submit(() -> performFilesBackup(defaultWorkspace, contentPathsFuture)); - } - } finally { - Jcr.logout(session); - } - - } - - protected Set performNodeBackup(String workspaceName, String nodePath) { - Session session = login(workspaceName); - try { - Node nodeToExport = session.getNode(nodePath); -// String nodeName = nodeToExport.getName(); -// if (nodeName.startsWith("jcr:") || nodeName.startsWith("rep:")) -// continue nodes; -// // TODO make it more robust / configurable -// if (nodeName.equals("user")) -// continue nodes; - String relativePath = WORKSPACES_BASE + workspaceName + nodePath + ".xml"; - OutputStream xmlOut = openOutputStream(relativePath); - BackupContentHandler contentHandler; - try (Writer writer = new BufferedWriter(new OutputStreamWriter(xmlOut, StandardCharsets.UTF_8))) { - contentHandler = new BackupContentHandler(writer, nodeToExport); - session.exportSystemView(nodeToExport.getPath(), contentHandler, true, false); - if (log.isDebugEnabled()) - log.debug(workspaceName + ":" + nodePath + " metadata exported to " + relativePath); - } - - // Files - Set contentPaths = contentHandler.getContentPaths(); - return contentPaths; - } catch (Exception e) { - markBackupFailed("Cannot backup node " + workspaceName + ":" + nodePath, e); - throw new ThreadDeath(); - } finally { - Jcr.logout(session); - } - } - - protected void performFilesBackup(String workspaceName, Future> contentPathsFuture) { - Set contentPaths; - try { - contentPaths = contentPathsFuture.get(24, TimeUnit.HOURS); - } catch (InterruptedException | ExecutionException | TimeoutException e1) { - markBackupFailed("Cannot retrieve content paths for workspace " + workspaceName, e1); - return; - } - if (contentPaths == null || contentPaths.size() == 0) - return; - Session session = login(workspaceName); - try { - String workspacesFilesBasePath = FILES_BASE + workspaceName; - for (String path : contentPaths) { - if (isBackupFailed()) - return; - Node contentNode = session.getNode(path); - Binary binary = null; - try { - binary = contentNode.getProperty(Property.JCR_DATA).getBinary(); - String fileRelativePath = workspacesFilesBasePath + contentNode.getParent().getPath(); - - // checksum - boolean skip = false; - String checksum = null; - if (session instanceof JackrabbitSession) { - JackrabbitValue value = (JackrabbitValue) contentNode.getProperty(Property.JCR_DATA).getValue(); -// ReferenceBinary referenceBinary = (ReferenceBinary) binary; - checksum = value.getContentIdentity(); - } - if (checksum != null) { - if (!checksums.containsKey(checksum)) { - checksums.put(checksum, fileRelativePath); - } else { - skip = true; - String sourcePath = checksums.get(checksum); - if (log.isTraceEnabled()) - log.trace(fileRelativePath + " : already " + sourcePath + " with checksum " + checksum); - createLink(sourcePath, fileRelativePath); - try (Writer writerSum = new OutputStreamWriter( - openOutputStream(fileRelativePath + ".sha256"), StandardCharsets.UTF_8)) { - writerSum.write(checksum); - } - } - } - - // copy file - if (!skip) - try (InputStream in = binary.getStream(); - OutputStream out = openOutputStream(fileRelativePath)) { - IOUtils.copy(in, out); - if (log.isTraceEnabled()) - log.trace("Workspace " + workspaceName + ": file content exported to " - + fileRelativePath); - } - } finally { - JcrUtils.closeQuietly(binary); - } - } - if (log.isDebugEnabled()) - log.debug(workspaceName + ":" + contentPaths.size() + " files exported to " + workspacesFilesBasePath); - } catch (Exception e) { - markBackupFailed("Cannot backup files from " + workspaceName + ":", e); - } finally { - Jcr.logout(session); - } - } - - protected OutputStream openOutputStream(String relativePath) throws IOException { - if (zout != null) { - ZipEntry entry = new ZipEntry(relativePath); - zout.putNextEntry(entry); - return zout; - } else if (basePath != null) { - Path targetPath = basePath.resolve(Paths.get(relativePath)); - Files.createDirectories(targetPath.getParent()); - return Files.newOutputStream(targetPath); - } else { - throw new UnsupportedOperationException(); - } - } - - protected void createLink(String source, String target) throws IOException { - if (zout != null) { - // TODO implement for zip - throw new UnsupportedOperationException(); - } else if (basePath != null) { - Path sourcePath = basePath.resolve(Paths.get(source)); - Path targetPath = basePath.resolve(Paths.get(target)); - Path relativeSource = targetPath.getParent().relativize(sourcePath); - Files.createDirectories(targetPath.getParent()); - Files.createSymbolicLink(targetPath, relativeSource); - } else { - throw new UnsupportedOperationException(); - } - } - - protected void closeOutputStream(String relativePath, OutputStream out) throws IOException { - if (zout != null) { - zout.closeEntry(); - } else if (basePath != null) { - out.close(); - } else { - throw new UnsupportedOperationException(); - } - } - - protected Session login(String workspaceName) { - if (bundleContext != null) {// local - return CmsJcrUtils.openDataAdminSession(repository, workspaceName); - } else {// remote - try { - return repository.login(workspaceName); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - } - - public final static void main(String[] args) throws Exception { - if (args.length == 0) { - printUsage("No argument"); - System.exit(1); - } - URI uri = new URI(args[0]); - Repository repository = createRemoteRepository(uri); - Path basePath = args.length > 1 ? Paths.get(args[1]) : Paths.get(System.getProperty("user.dir")); - if (!Files.exists(basePath)) - Files.createDirectories(basePath); - LogicalBackup backup = new LogicalBackup(null, repository, basePath); - backup.run(); - } - - private static void printUsage(String errorMessage) { - if (errorMessage != null) - System.err.println(errorMessage); - System.out.println("Usage: LogicalBackup []"); - - } - - protected static Repository createRemoteRepository(URI uri) throws RepositoryException { - RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory(); - Map params = new HashMap(); - params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, uri.toString()); - // TODO make it configurable - params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, CmsConstants.SYS_WORKSPACE); - return repositoryFactory.getRepository(params); - } - - public void performSoftwareBackup(BundleContext bundleContext) { - String bootBasePath = OSGI_BASE + "boot"; - Bundle[] bundles = bundleContext.getBundles(); - for (Bundle bundle : bundles) { - String relativePath = bootBasePath + "/" + bundle.getSymbolicName() + ".jar"; - Dictionary headers = bundle.getHeaders(); - Manifest manifest = new Manifest(); - Enumeration headerKeys = headers.keys(); - while (headerKeys.hasMoreElements()) { - String headerKey = headerKeys.nextElement(); - String headerValue = headers.get(headerKey); - manifest.getMainAttributes().putValue(headerKey, headerValue); - } - try (JarOutputStream jarOut = new JarOutputStream(openOutputStream(relativePath), manifest)) { - Enumeration resourcePaths = bundle.findEntries("/", "*", true); - resources: while (resourcePaths.hasMoreElements()) { - URL entryUrl = resourcePaths.nextElement(); - String entryPath = entryUrl.getPath(); - if (entryPath.equals("")) - continue resources; - if (entryPath.endsWith("/")) - continue resources; - String entryName = entryPath.substring(1);// remove first '/' - if (entryUrl.getPath().equals("/META-INF/")) - continue resources; - if (entryUrl.getPath().equals("/META-INF/MANIFEST.MF")) - continue resources; - // dev - if (entryUrl.getPath().startsWith("/target")) - continue resources; - if (entryUrl.getPath().startsWith("/src")) - continue resources; - if (entryUrl.getPath().startsWith("/ext")) - continue resources; - - if (entryName.startsWith("bin/")) {// dev - entryName = entryName.substring("bin/".length()); - } - - ZipEntry entry = new ZipEntry(entryName); - try (InputStream in = entryUrl.openStream()) { - try { - jarOut.putNextEntry(entry); - } catch (ZipException e) {// duplicate - continue resources; - } - IOUtils.copy(in, jarOut); - jarOut.closeEntry(); -// log.info(entryUrl); - } catch (FileNotFoundException e) { - log.warn(entryUrl + ": " + e.getMessage()); - } - } - } catch (IOException e1) { - throw new RuntimeException("Cannot export bundle " + bundle, e1); - } - } - if (log.isDebugEnabled()) - log.debug(bundles.length + " OSGi bundles exported to " + bootBasePath); - - } - - protected synchronized void markBackupFailed(Object message, Exception e) { - log.error(message, e); - backupFailed = true; - notifyAll(); - if (executorService != null) - executorService.shutdownNow(); - } - - protected boolean isBackupFailed() { - return backupFailed; - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalRestore.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalRestore.java deleted file mode 100644 index 122c96701..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/LogicalRestore.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.argeo.maintenance.backup; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; - -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.osgi.framework.BundleContext; - -/** Restores a backup in the format defined by {@link LogicalBackup}. */ -public class LogicalRestore implements Runnable { - private final static CmsLog log = CmsLog.getLog(LogicalRestore.class); - - private final Repository repository; - private final BundleContext bundleContext; - private final Path basePath; - - public LogicalRestore(BundleContext bundleContext, Repository repository, Path basePath) { - this.repository = repository; - this.basePath = basePath; - this.bundleContext = bundleContext; - } - - @Override - public void run() { - Path workspaces = basePath.resolve(LogicalBackup.WORKSPACES_BASE); - try { - // import jcr:system first -// Session defaultSession = NodeUtils.openDataAdminSession(repository, null); -// try (DirectoryStream xmls = Files.newDirectoryStream( -// workspaces.resolve(NodeConstants.SYS_WORKSPACE + LogicalBackup.JCR_VERSION_STORAGE_PATH), -// "*.xml")) { -// for (Path xml : xmls) { -// try (InputStream in = Files.newInputStream(xml)) { -// defaultSession.getWorkspace().importXML(LogicalBackup.JCR_VERSION_STORAGE_PATH, in, -// ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); -// if (log.isDebugEnabled()) -// log.debug("Restored " + xml + " to " + defaultSession.getWorkspace().getName() + ":"); -// } -// } -// } finally { -// Jcr.logout(defaultSession); -// } - - // non-system content - try (DirectoryStream workspaceDirs = Files.newDirectoryStream(workspaces)) { - for (Path workspacePath : workspaceDirs) { - String workspaceName = workspacePath.getFileName().toString(); - Session session = JcrUtils.loginOrCreateWorkspace(repository, workspaceName); - try (DirectoryStream xmls = Files.newDirectoryStream(workspacePath, "*.xml")) { - xmls: for (Path xml : xmls) { - if (xml.getFileName().toString().startsWith("rep:")) - continue xmls; - try (InputStream in = Files.newInputStream(xml)) { - session.getWorkspace().importXML("/", in, - ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); - if (log.isDebugEnabled()) - log.debug("Restored " + xml + " to workspace " + workspaceName); - } - } - } finally { - Jcr.logout(session); - } - } - } - } catch (IOException e) { - throw new RuntimeException("Cannot restore backup from " + basePath, e); - } catch (RepositoryException e) { - throw new JcrException("Cannot restore backup from " + basePath, e); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/package-info.java deleted file mode 100644 index a61e19bd4..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/backup/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Argeo Node backup utilities. */ -package org.argeo.maintenance.backup; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/internal/Activator.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/internal/Activator.java deleted file mode 100644 index ef40ab3a3..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/internal/Activator.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.argeo.maintenance.internal; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import javax.jcr.Repository; - -import org.argeo.maintenance.backup.LogicalBackup; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class Activator implements BundleActivator { - - @Override - public void start(BundleContext context) throws Exception { - // Start backup - Repository repository = context.getService(context.getServiceReference(Repository.class)); - Path basePath = Paths.get(System.getProperty("user.dir"), "backup"); - LogicalBackup backup = new LogicalBackup(context, repository, basePath); - backup.run(); - } - - @Override - public void stop(BundleContext context) throws Exception { - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/package-info.java deleted file mode 100644 index 1ce974c6f..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Utilities for the maintenance of an Argeo Node. */ -package org.argeo.maintenance; \ No newline at end of file diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java deleted file mode 100644 index bffe531a1..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.util.Map; -import java.util.Set; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.jackrabbit.core.security.authorization.acl.ACLProvider; - -/** Argeo specific access control provider */ -public class ArgeoAccessControlProvider extends ACLProvider { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public void init(Session systemSession, Map configuration) throws RepositoryException { - if (!configuration.containsKey(PARAM_ALLOW_UNKNOWN_PRINCIPALS)) - configuration.put(PARAM_ALLOW_UNKNOWN_PRINCIPALS, "true"); - if (!configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS)) - configuration.put(PARAM_OMIT_DEFAULT_PERMISSIONS, "true"); - super.init(systemSession, configuration); - } - - @Override - public boolean canAccessRoot(Set principals) throws RepositoryException { - return super.canAccessRoot(principals); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java deleted file mode 100644 index 7464078d8..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.argeo.security.jackrabbit; - -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.core.id.ItemId; -import org.apache.jackrabbit.core.security.DefaultAccessManager; -import org.apache.jackrabbit.spi.Path; - -/** - * Intermediary class in order to have a consistent naming in config files. Does - * nothing for the time being, but may in the future. - */ -public class ArgeoAccessManager extends DefaultAccessManager { - - @Override - public boolean canRead(Path itemPath, ItemId itemId) - throws RepositoryException { - return super.canRead(itemPath, itemId); - } - - @Override - public Privilege[] getPrivileges(String absPath) - throws PathNotFoundException, RepositoryException { - return super.getPrivileges(absPath); - } - - @Override - public boolean hasPrivileges(String absPath, Privilege[] privileges) - throws PathNotFoundException, RepositoryException { - return super.hasPrivileges(absPath, privileges); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java deleted file mode 100644 index d679c45f9..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.argeo.security.jackrabbit; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -import org.apache.jackrabbit.core.security.authentication.AuthContext; - -/** Wraps a regular {@link LoginContext}, using the proper class loader. */ -class ArgeoAuthContext implements AuthContext { - private LoginContext lc; - - public ArgeoAuthContext(String appName, Subject subject, CallbackHandler callbackHandler) { - try { - lc = new LoginContext(appName, subject, callbackHandler); - } catch (LoginException e) { - throw new IllegalStateException("Cannot configure Jackrabbit login context", e); - } - } - - @Override - public void login() throws LoginException { - lc.login(); - } - - @Override - public Subject getSubject() { - return lc.getSubject(); - } - - @Override - public void logout() throws LoginException { - lc.logout(); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java deleted file mode 100644 index 97acf66ef..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.util.HashSet; -import java.util.Properties; -import java.util.Set; - -import javax.jcr.Credentials; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.x500.X500Principal; - -import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.core.DefaultSecurityManager; -import org.apache.jackrabbit.core.security.AMContext; -import org.apache.jackrabbit.core.security.AccessManager; -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.SystemPrincipal; -import org.apache.jackrabbit.core.security.authentication.AuthContext; -import org.apache.jackrabbit.core.security.authentication.CallbackHandlerImpl; -import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; -import org.apache.jackrabbit.core.security.principal.PrincipalProvider; -import org.argeo.api.cms.AnonymousPrincipal; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.DataAdminPrincipal; - -/** Customises Jackrabbit security. */ -public class ArgeoSecurityManager extends DefaultSecurityManager { - private final static CmsLog log = CmsLog.getLog(ArgeoSecurityManager.class); - -// private BundleContext cmsBundleContext = null; - - public ArgeoSecurityManager() { -// if (FrameworkUtil.getBundle(CmsSession.class) != null) { -// cmsBundleContext = FrameworkUtil.getBundle(CmsSession.class).getBundleContext(); -// } - } - - public AuthContext getAuthContext(Credentials creds, Subject subject, String workspaceName) - throws RepositoryException { - checkInitialized(); - - CallbackHandler cbHandler = new CallbackHandlerImpl(creds, getSystemSession(), getPrincipalProviderRegistry(), - adminId, anonymousId); - String appName = "Jackrabbit"; - return new ArgeoAuthContext(appName, subject, cbHandler); - } - - @Override - public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException { - synchronized (getSystemSession()) { - return super.getAccessManager(session, amContext); - } - } - - @Override - public UserManager getUserManager(Session session) throws RepositoryException { - synchronized (getSystemSession()) { - return super.getUserManager(session); - } - } - - @Override - protected PrincipalProvider createDefaultPrincipalProvider(Properties[] moduleConfig) throws RepositoryException { - return super.createDefaultPrincipalProvider(moduleConfig); - } - - /** Called once when the session is created */ - @Override - public String getUserID(Subject subject, String workspaceName) throws RepositoryException { - boolean isAnonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty(); - boolean isDataAdmin = !subject.getPrincipals(DataAdminPrincipal.class).isEmpty(); - boolean isJackrabbitSystem = !subject.getPrincipals(SystemPrincipal.class).isEmpty(); - Set userPrincipal = subject.getPrincipals(X500Principal.class); - boolean isRegularUser = !userPrincipal.isEmpty(); -// CmsSession cmsSession = null; -// if (cmsBundleContext != null) { -// cmsSession = CmsOsgiUtils.getCmsSession(cmsBundleContext, subject); -// if (log.isTraceEnabled()) -// log.trace("Opening JCR session for CMS session " + cmsSession); -// } - - if (isAnonymous) { - if (isDataAdmin || isJackrabbitSystem || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else - return CmsConstants.ROLE_ANONYMOUS; - } else if (isRegularUser) {// must be before DataAdmin - if (isAnonymous || isJackrabbitSystem) - throw new IllegalStateException("Inconsistent " + subject); - else { - if (userPrincipal.size() > 1) { - StringBuilder buf = new StringBuilder(); - for (X500Principal principal : userPrincipal) - buf.append(' ').append('\"').append(principal).append('\"'); - throw new RuntimeException("Multiple user principals:" + buf); - } - return userPrincipal.iterator().next().getName(); - } - } else if (isDataAdmin) { - if (isAnonymous || isJackrabbitSystem || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else { - assert !subject.getPrincipals(AdminPrincipal.class).isEmpty(); - return CmsConstants.ROLE_DATA_ADMIN; - } - } else if (isJackrabbitSystem) { - if (isAnonymous || isDataAdmin || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else - return super.getUserID(subject, workspaceName); - } else { - throw new IllegalStateException("Unrecognized subject type: " + subject); - } - } - - @Override - protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { - WorkspaceAccessManager wam = super.createDefaultWorkspaceAccessManager(); - ArgeoWorkspaceAccessManagerImpl workspaceAccessManager = new ArgeoWorkspaceAccessManagerImpl(wam); - if (log.isTraceEnabled()) - log.trace("Created workspace access manager"); - return workspaceAccessManager; - } - - private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager { - private final WorkspaceAccessManager wam; - - public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) { - super(); - this.wam = wam; - } - - public void init(Session systemSession) throws RepositoryException { - wam.init(systemSession); - Repository repository = systemSession.getRepository(); - if (log.isTraceEnabled()) - log.trace("Initialised workspace access manager on repository " + repository - + ", systemSession workspace: " + systemSession.getWorkspace().getName()); - } - - public void close() throws RepositoryException { - } - - public boolean grants(Set principals, String workspaceName) throws RepositoryException { - // TODO: implements finer access to workspaces - if (log.isTraceEnabled()) - log.trace("Grants " + new HashSet<>(principals) + " access to workspace '" + workspaceName + "'"); - return true; - // return wam.grants(principals, workspaceName); - } - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java deleted file mode 100644 index 0f63957b7..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.argeo.security.jackrabbit; - -import java.util.Map; -import java.util.Set; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; -import javax.security.auth.x500.X500Principal; - -import org.apache.jackrabbit.core.security.AnonymousPrincipal; -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; -import org.argeo.api.cms.DataAdminPrincipal; - -/** JAAS login module used when initiating a new Jackrabbit session. */ -public class SystemJackrabbitLoginModule implements LoginModule { - private Subject subject; - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, - Map options) { - this.subject = subject; - } - - @Override - public boolean login() throws LoginException { - return true; - } - - @Override - public boolean commit() throws LoginException { - Set anonPrincipal = subject - .getPrincipals(org.argeo.api.cms.AnonymousPrincipal.class); - if (!anonPrincipal.isEmpty()) { - subject.getPrincipals().add(new AnonymousPrincipal()); - return true; - } - - Set initPrincipal = subject.getPrincipals(DataAdminPrincipal.class); - if (!initPrincipal.isEmpty()) { - subject.getPrincipals().add(new AdminPrincipal(SecurityConstants.ADMIN_ID)); - return true; - } - - Set userPrincipal = subject.getPrincipals(X500Principal.class); - if (userPrincipal.isEmpty()) - throw new LoginException("Subject must be pre-authenticated"); - if (userPrincipal.size() > 1) - throw new LoginException("Multiple user principals " + userPrincipal); - - return true; - } - - @Override - public boolean abort() throws LoginException { - return true; - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class)); - subject.getPrincipals().removeAll(subject.getPrincipals(AdminPrincipal.class)); - return true; - } -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/package-info.java b/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/package-info.java deleted file mode 100644 index 8529cc207..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Integration of Jackrabbit with Argeo security model. */ -package org.argeo.security.jackrabbit; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/bnd.bnd b/swt/org.argeo.cms.e4/bnd.bnd index 10de62552..7cf086181 100644 --- a/swt/org.argeo.cms.e4/bnd.bnd +++ b/swt/org.argeo.cms.e4/bnd.bnd @@ -9,12 +9,11 @@ org.eclipse.swt,\ org.eclipse.swt.widgets;version="0.0.0",\ org.eclipse.e4.ui.model.application.ui,\ org.eclipse.e4.ui.model.application,\ -javax.jcr.nodetype,\ org.argeo.cms,\ org.eclipse.core.commands.common,\ org.eclipse.jface.window,\ +org.eclipse.jface.dialogs,\ org.argeo.cms.swt.auth,\ -org.apache.jackrabbit.*;version="[2,3)",\ javax.servlet.*;version="[3,5)",\ * diff --git a/swt/org.argeo.cms.e4/e4xmi/cms-devops.e4xmi b/swt/org.argeo.cms.e4/e4xmi/cms-devops.e4xmi index 347cd66fd..f71b83e1f 100644 --- a/swt/org.argeo.cms.e4/e4xmi/cms-devops.e4xmi +++ b/swt/org.argeo.cms.e4/e4xmi/cms-devops.e4xmi @@ -9,9 +9,9 @@ auth.cn=admin,ou=roles,ou=node - - - + + + @@ -22,9 +22,9 @@ usersEditorArea - - - + + + @@ -94,15 +94,15 @@ - - - - - + + + + + - - + + diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java index e84b18c0b..37f1c0233 100644 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java +++ b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java @@ -96,6 +96,8 @@ public class AuthAddon { } catch (Exception e) { throw new CmsException("Cannot log out", e); } + + // FIXME make it more generic HttpServletRequest request = org.argeo.eclipse.ui.specific.UiContext.getHttpRequest(); if (request != null) request.getSession().setMaxInactiveInterval(0); diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java index 579d35d6a..aabfbf5dd 100644 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java +++ b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java @@ -9,9 +9,6 @@ import java.nio.file.spi.FileSystemProvider; import javax.annotation.PostConstruct; import javax.inject.Inject; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.swt.CmsException; -import org.argeo.eclipse.ui.fs.AdvancedFsBrowser; import org.argeo.eclipse.ui.fs.SimpleFsBrowser; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; @@ -27,7 +24,7 @@ public class NodeFsBrowserView { @PostConstruct public void createPartControl(Composite parent) { try { - //URI uri = new URI("node://root:demo@localhost:7070/"); + // URI uri = new URI("node://root:demo@localhost:7070/"); URI uri = new URI("node:///"); FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri); if (fileSystem == null) @@ -41,7 +38,7 @@ public class NodeFsBrowserView { // AdvancedFsBrowser browser = new AdvancedFsBrowser(); // browser.createUi(parent, localPath); } catch (Exception e) { - throw new CmsException("Cannot open file system browser", e); + throw new RuntimeException("Cannot open file system browser", e); } } diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/EclipseJcrMonitor.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/EclipseJcrMonitor.java deleted file mode 100644 index e10738ee0..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/EclipseJcrMonitor.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import org.argeo.jcr.JcrMonitor; -import org.eclipse.core.runtime.IProgressMonitor; - -/** - * Wraps an Eclipse {@link IProgressMonitor} so that it can be passed to - * framework agnostic Argeo routines. - */ -public class EclipseJcrMonitor implements JcrMonitor { - private final IProgressMonitor progressMonitor; - - public EclipseJcrMonitor(IProgressMonitor progressMonitor) { - this.progressMonitor = progressMonitor; - } - - public void beginTask(String name, int totalWork) { - progressMonitor.beginTask(name, totalWork); - } - - public void done() { - progressMonitor.done(); - } - - public boolean isCanceled() { - return progressMonitor.isCanceled(); - } - - public void setCanceled(boolean value) { - progressMonitor.setCanceled(value); - } - - public void setTaskName(String name) { - progressMonitor.setTaskName(name); - } - - public void subTask(String name) { - progressMonitor.subTask(name); - } - - public void worked(int work) { - progressMonitor.worked(work); - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/GenericPropertyPage.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/GenericPropertyPage.java deleted file mode 100644 index e17f17bb7..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/GenericPropertyPage.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; - -import org.argeo.cms.ui.jcr.PropertyLabelProvider; -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.layout.TreeColumnLayout; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.IBaseLabelProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; - -/** - * Generic editor property page. Lists all properties of current node as a - * complex tree. TODO: enable editing - */ -public class GenericPropertyPage { - - // Main business Objects - private Node currentNode; - - public GenericPropertyPage(Node currentNode) { - this.currentNode = currentNode; - } - - protected void createFormContent(Composite parent) { - Composite innerBox = new Composite(parent, SWT.NONE); - // Composite innerBox = new Composite(body, SWT.NO_FOCUS); - FillLayout layout = new FillLayout(); - layout.marginHeight = 5; - layout.marginWidth = 5; - innerBox.setLayout(layout); - createComplexTree(innerBox); - // TODO TreeColumnLayout triggers a scroll issue with the form: - // The inside body is always to big and a scroll bar is shown - // Composite tableCmp = new Composite(body, SWT.NO_FOCUS); - // createComplexTree(tableCmp); - } - - private TreeViewer createComplexTree(Composite parent) { - int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION; - Tree tree = new Tree(parent, style); - TreeColumnLayout tableColumnLayout = new TreeColumnLayout(); - - createColumn(tree, tableColumnLayout, "Property", SWT.LEFT, 200, 30); - createColumn(tree, tableColumnLayout, "Value(s)", SWT.LEFT, 300, 60); - createColumn(tree, tableColumnLayout, "Type", SWT.LEFT, 75, 10); - createColumn(tree, tableColumnLayout, "Attributes", SWT.LEFT, 75, 0); - // Do not apply the treeColumnLayout it does not work yet - // parent.setLayout(tableColumnLayout); - - tree.setLinesVisible(true); - tree.setHeaderVisible(true); - - TreeViewer treeViewer = new TreeViewer(tree); - treeViewer.setContentProvider(new TreeContentProvider()); - treeViewer.setLabelProvider((IBaseLabelProvider) new PropertyLabelProvider()); - treeViewer.setInput(currentNode); - treeViewer.expandAll(); - return treeViewer; - } - - private static TreeColumn createColumn(Tree parent, TreeColumnLayout tableColumnLayout, String name, int style, - int width, int weight) { - TreeColumn column = new TreeColumn(parent, style); - column.setText(name); - column.setWidth(width); - column.setMoveable(true); - column.setResizable(true); - tableColumnLayout.setColumnData(column, new ColumnWeightData(weight, width, true)); - return column; - } - - private class TreeContentProvider implements ITreeContentProvider { - private static final long serialVersionUID = -6162736530019406214L; - - public Object[] getElements(Object parent) { - Object[] props = null; - try { - - if (parent instanceof Node) { - Node node = (Node) parent; - PropertyIterator pi; - pi = node.getProperties(); - List propList = new ArrayList(); - while (pi.hasNext()) { - propList.add(pi.nextProperty()); - } - props = propList.toArray(); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Unexpected exception while listing node properties", e); - } - return props; - } - - public Object getParent(Object child) { - return null; - } - - public Object[] getChildren(Object parent) { - if (parent instanceof Property) { - Property prop = (Property) parent; - try { - if (prop.isMultiple()) - return prop.getValues(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get multi-prop values on " + prop, e); - } - } - return null; - } - - public boolean hasChildren(Object parent) { - try { - return (parent instanceof Property && ((Property) parent).isMultiple()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check if property is multiple for " + parent, e); - } - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - public void dispose() { - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java deleted file mode 100644 index 0b77c0732..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java +++ /dev/null @@ -1,349 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.inject.Inject; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.security.CryptoKeyring; -import org.argeo.cms.security.Keyring; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.jcr.JcrBrowserUtils; -import org.argeo.cms.ui.jcr.NodeContentProvider; -import org.argeo.cms.ui.jcr.NodeLabelProvider; -import org.argeo.cms.ui.jcr.OsgiRepositoryRegister; -import org.argeo.cms.ui.jcr.PropertiesContentProvider; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; -import org.argeo.eclipse.ui.jcr.util.NodeViewerComparer; -import org.argeo.jcr.JcrUtils; -import org.eclipse.e4.core.contexts.IEclipseContext; -import org.eclipse.e4.core.di.annotations.Optional; -import org.eclipse.e4.ui.services.EMenuService; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IBaseLabelProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; - -/** - * Basic View to display a sash form to browse a JCR compliant multiple - * repository environment - */ -public class JcrBrowserView { - final static String ID = "org.argeo.cms.e4.jcrbrowser"; - final static String NODE_VIEWER_POPUP_MENU_ID = "org.argeo.cms.e4.popupmenu.nodeViewer"; - - private boolean sortChildNodes = true; - - /* DEPENDENCY INJECTION */ - @Inject - @Optional - private Keyring keyring; - @Inject - private RepositoryFactory repositoryFactory; - @Inject - private Repository nodeRepository; - - // Current user session on the home repository default workspace - private Session userSession; - - private OsgiRepositoryRegister repositoryRegister = new OsgiRepositoryRegister(); - - // This page widgets - private TreeViewer nodesViewer; - private NodeContentProvider nodeContentProvider; - private TableViewer propertiesViewer; - private EventListener resultsObserver; - - @PostConstruct - public void createPartControl(Composite parent, IEclipseContext context, EPartService partService, - ESelectionService selectionService, EMenuService menuService) { - repositoryRegister.init(); - - parent.setLayout(new FillLayout()); - SashForm sashForm = new SashForm(parent, SWT.VERTICAL); - // sashForm.setSashWidth(4); - // sashForm.setLayout(new FillLayout()); - - // Create the tree on top of the view - Composite top = new Composite(sashForm, SWT.NONE); - // GridLayout gl = new GridLayout(1, false); - top.setLayout(CmsSwtUtils.noSpaceGridLayout()); - - try { - this.userSession = this.nodeRepository.login(CmsConstants.HOME_WORKSPACE); - } catch (RepositoryException e) { - throw new CmsException("Cannot open user session", e); - } - - nodeContentProvider = new NodeContentProvider(userSession, keyring, repositoryRegister, repositoryFactory, - sortChildNodes); - - // nodes viewer - nodesViewer = createNodeViewer(top, nodeContentProvider); - - // context menu : it is completely defined in the plugin.xml file. - // MenuManager menuManager = new MenuManager(); - // Menu menu = menuManager.createContextMenu(nodesViewer.getTree()); - - // nodesViewer.getTree().setMenu(menu); - - nodesViewer.setInput(""); - - // Create the property viewer on the bottom - Composite bottom = new Composite(sashForm, SWT.NONE); - bottom.setLayout(CmsSwtUtils.noSpaceGridLayout()); - propertiesViewer = createPropertiesViewer(bottom); - - sashForm.setWeights(getWeights()); - nodesViewer.setComparer(new NodeViewerComparer()); - nodesViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - selectionService.setSelection(selection.toList()); - } - }); - nodesViewer.addDoubleClickListener(new JcrE4DClickListener(nodesViewer, partService)); - menuService.registerContextMenu(nodesViewer.getControl(), NODE_VIEWER_POPUP_MENU_ID); - // getSite().registerContextMenu(menuManager, nodesViewer); - // getSite().setSelectionProvider(nodesViewer); - } - - @PreDestroy - public void dispose() { - JcrUtils.logoutQuietly(userSession); - repositoryRegister.destroy(); - } - - public void refresh(Object obj) { - // Enable full refresh from a command when no element of the tree is - // selected - if (obj == null) { - Object[] elements = nodeContentProvider.getElements(null); - for (Object el : elements) { - if (el instanceof TreeParent) - JcrBrowserUtils.forceRefreshIfNeeded((TreeParent) el); - getNodeViewer().refresh(el); - } - } else - getNodeViewer().refresh(obj); - } - - /** - * To be overridden to adapt size of form and result frames. - */ - protected int[] getWeights() { - return new int[] { 70, 30 }; - } - - protected TreeViewer createNodeViewer(Composite parent, final ITreeContentProvider nodeContentProvider) { - - final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); - - tmpNodeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - tmpNodeViewer.setContentProvider(nodeContentProvider); - tmpNodeViewer.setLabelProvider((IBaseLabelProvider) new NodeLabelProvider()); - tmpNodeViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - if (!event.getSelection().isEmpty()) { - IStructuredSelection sel = (IStructuredSelection) event.getSelection(); - Object firstItem = sel.getFirstElement(); - if (firstItem instanceof SingleJcrNodeElem) - propertiesViewer.setInput(((SingleJcrNodeElem) firstItem).getNode()); - } else { - propertiesViewer.setInput(""); - } - } - }); - - resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay()); - if (keyring != null) - try { - ObservationManager observationManager = userSession.getWorkspace().getObservationManager(); - observationManager.addEventListener(resultsObserver, Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/", - true, null, null, false); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot register listeners", e); - } - - // tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer)); - return tmpNodeViewer; - } - - protected TableViewer createPropertiesViewer(Composite parent) { - propertiesViewer = new TableViewer(parent, SWT.NONE); - propertiesViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - propertiesViewer.getTable().setHeaderVisible(true); - propertiesViewer.setContentProvider(new PropertiesContentProvider()); - TableViewerColumn col = new TableViewerColumn(propertiesViewer, SWT.NONE); - col.getColumn().setText("Name"); - col.getColumn().setWidth(200); - col.setLabelProvider(new ColumnLabelProvider() { - private static final long serialVersionUID = -6684361063107478595L; - - public String getText(Object element) { - try { - return ((Property) element).getName(); - } catch (RepositoryException e) { - throw new EclipseUiException("Unexpected exception in label provider", e); - } - } - }); - col = new TableViewerColumn(propertiesViewer, SWT.NONE); - col.getColumn().setText("Value"); - col.getColumn().setWidth(400); - col.setLabelProvider(new ColumnLabelProvider() { - private static final long serialVersionUID = -8201994187693336657L; - - public String getText(Object element) { - try { - Property property = (Property) element; - if (property.getType() == PropertyType.BINARY) - return ""; - else if (property.isMultiple()) { - StringBuffer buf = new StringBuffer("["); - Value[] values = property.getValues(); - for (int i = 0; i < values.length; i++) { - if (i != 0) - buf.append(", "); - buf.append(values[i].getString()); - } - buf.append(']'); - return buf.toString(); - } else - return property.getValue().getString(); - } catch (RepositoryException e) { - throw new EclipseUiException("Unexpected exception in label provider", e); - } - } - }); - col = new TableViewerColumn(propertiesViewer, SWT.NONE); - col.getColumn().setText("Type"); - col.getColumn().setWidth(200); - col.setLabelProvider(new ColumnLabelProvider() { - private static final long serialVersionUID = -6009599998150286070L; - - public String getText(Object element) { - return JcrBrowserUtils.getPropertyTypeAsString((Property) element); - } - }); - propertiesViewer.setInput(""); - return propertiesViewer; - } - - protected TreeViewer getNodeViewer() { - return nodesViewer; - } - - /** - * Resets the tree content provider - * - * @param sortChildNodes if true the content provider will use a comparer to - * sort nodes that might slow down the display - */ - public void setSortChildNodes(boolean sortChildNodes) { - this.sortChildNodes = sortChildNodes; - ((NodeContentProvider) nodesViewer.getContentProvider()).setSortChildren(sortChildNodes); - nodesViewer.setInput(""); - } - - /** Notifies the current view that a node has been added */ - public void nodeAdded(TreeParent parentNode) { - // insure that Ui objects have been correctly created: - JcrBrowserUtils.forceRefreshIfNeeded(parentNode); - getNodeViewer().refresh(parentNode); - getNodeViewer().expandToLevel(parentNode, 1); - } - - /** Notifies the current view that a node has been removed */ - public void nodeRemoved(TreeParent parentNode) { - IStructuredSelection newSel = new StructuredSelection(parentNode); - getNodeViewer().setSelection(newSel, true); - // Force refresh - IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer().getSelection(); - getNodeViewer().refresh(tmpSel.getFirstElement()); - } - - class TreeObserver extends AsyncUiEventListener { - - public TreeObserver(Display display) { - super(display); - } - - @Override - protected Boolean willProcessInUiThread(List events) throws RepositoryException { - for (Event event : events) { - if (getLog().isTraceEnabled()) - getLog().debug("Received event " + event); - String path = event.getPath(); - int index = path.lastIndexOf('/'); - String propertyName = path.substring(index + 1); - if (getLog().isTraceEnabled()) - getLog().debug("Concerned property " + propertyName); - } - return false; - } - - protected void onEventInUiThread(List events) throws RepositoryException { - if (getLog().isTraceEnabled()) - getLog().trace("Refresh result list"); - nodesViewer.refresh(); - } - - } - - public boolean getSortChildNodes() { - return sortChildNodes; - } - - public void setFocus() { - getNodeViewer().getTree().setFocus(); - } - - /* DEPENDENCY INJECTION */ - // public void setRepositoryRegister(RepositoryRegister repositoryRegister) { - // this.repositoryRegister = repositoryRegister; - // } - - public void setKeyring(CryptoKeyring keyring) { - this.keyring = keyring; - } - - public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - this.repositoryFactory = repositoryFactory; - } - - public void setNodeRepository(Repository nodeRepository) { - this.nodeRepository = nodeRepository; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java deleted file mode 100644 index f4ee2e8da..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.ui.jcr.JcrDClickListener; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; -import org.eclipse.jface.viewers.TreeViewer; - -public class JcrE4DClickListener extends JcrDClickListener { - EPartService partService; - - public JcrE4DClickListener(TreeViewer nodeViewer, EPartService partService) { - super(nodeViewer); - this.partService = partService; - } - - @Override - protected void openNode(Node node) { - MPart part = partService.createPart(JcrNodeEditor.DESCRIPTOR_ID); - try { - part.setLabel(node.getName()); - part.getPersistedState().put("nodeWorkspace", node.getSession().getWorkspace().getName()); - part.getPersistedState().put("nodePath", node.getPath()); - } catch (RepositoryException e) { - throw new CmsException("Cannot open " + node, e); - } - - // the provided part is be shown - partService.showPart(part, PartState.ACTIVATE); - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrNodeEditor.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrNodeEditor.java deleted file mode 100644 index ae2b325f5..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrNodeEditor.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.jcr.Node; - -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; - -public class JcrNodeEditor { - final static String DESCRIPTOR_ID = "org.argeo.cms.e4.partdescriptor.nodeEditor"; - - @PostConstruct - public void createUi(Composite parent, MPart part, ESelectionService selectionService) { - parent.setLayout(new FillLayout()); - List selection = (List) selectionService.getSelection(); - Node node = ((SingleJcrNodeElem) selection.get(0)).getNode(); - GenericPropertyPage propertyPage = new GenericPropertyPage(node); - propertyPage.createFormContent(parent); - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/SimplePart.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/SimplePart.java deleted file mode 100644 index 17d8d2a23..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/SimplePart.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.cms.e4.jcr; - -import javax.annotation.PostConstruct; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; - -public class SimplePart { - - @PostConstruct - void init(Composite parent) { - parent.setLayout(new GridLayout()); - Label label = new Label(parent, SWT.NONE); - label.setText("Hello e4 World"); - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java deleted file mode 100644 index 09fa760cd..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.argeo.cms.e4.jcr.handlers; - -import java.util.List; - -import javax.inject.Named; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.cms.e4.jcr.JcrBrowserView; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; - -/** - * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and - * {@link WorkspaceElem} TreeObject types. - * - * This handler assumes that a selection provider is available and picks only - * first selected item. It is UI's job to enable the command only when the - * selection contains one and only one element. Thus no parameter is passed - * through the command. - */ -public class AddFolderNode { - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - List selection = (List) selectionService.getSelection(); - JcrBrowserView view = (JcrBrowserView) part.getObject(); - - if (selection != null && selection.size() == 1) { - TreeParent treeParentNode = null; - Node jcrParentNode = null; - Object obj = selection.get(0); - - if (obj instanceof SingleJcrNodeElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); - } else if (obj instanceof WorkspaceElem) { - treeParentNode = (TreeParent) obj; - jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); - } else - return; - - String folderName = SingleValue.ask("Folder name", "Enter folder name"); - if (folderName != null) { - try { - jcrParentNode.addNode(folderName, NodeType.NT_FOLDER); - jcrParentNode.getSession().save(); - view.nodeAdded(treeParentNode); - } catch (RepositoryException e) { - ErrorFeedback.show("Cannot create folder " + folderName + " under " + treeParentNode, e); - } - } - } else { - // ErrorFeedback.show(WorkbenchUiPlugin - // .getMessage("errorUnvalidNtFolderNodeType")); - ErrorFeedback.show("Invalid NT folder node type"); - } - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddRemoteRepository.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddRemoteRepository.java deleted file mode 100644 index dc47f6edf..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddRemoteRepository.java +++ /dev/null @@ -1,210 +0,0 @@ -package org.argeo.cms.e4.jcr.handlers; - -import java.net.URI; -import java.util.Hashtable; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryFactory; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.ArgeoNames; -import org.argeo.cms.ArgeoTypes; -import org.argeo.cms.e4.jcr.JcrBrowserView; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.security.Keyring; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.jcr.JcrUtils; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.core.di.annotations.Optional; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -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.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** - * Connect to a remote repository and, if successful publish it as an OSGi - * service. - */ -public class AddRemoteRepository { - - @Inject - private RepositoryFactory repositoryFactory; - @Inject - private Repository nodeRepository; - @Inject - @Optional - private Keyring keyring; - - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part) { - JcrBrowserView view = (JcrBrowserView) part.getObject(); - RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog(Display.getDefault().getActiveShell()); - if (dlg.open() == Dialog.OK) { - view.refresh(null); - } - } - - // public void setRepositoryFactory(RepositoryFactory repositoryFactory) { - // this.repositoryFactory = repositoryFactory; - // } - // - // public void setKeyring(Keyring keyring) { - // this.keyring = keyring; - // } - // - // public void setNodeRepository(Repository nodeRepository) { - // this.nodeRepository = nodeRepository; - // } - - class RemoteRepositoryLoginDialog extends TitleAreaDialog { - private static final long serialVersionUID = 2234006887750103399L; - private Text name; - private Text uri; - private Text username; - private Text password; - private Button saveInKeyring; - - public RemoteRepositoryLoginDialog(Shell parentShell) { - super(parentShell); - } - - protected Point getInitialSize() { - return new Point(600, 400); - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - setMessage("Login to remote repository", IMessageProvider.NONE); - name = createLT(composite, "Name", "remoteRepository"); - uri = createLT(composite, "URI", "http://localhost:7070/jcr/node"); - username = createLT(composite, "User", ""); - password = createLP(composite, "Password"); - - saveInKeyring = createLC(composite, "Remember password", false); - parent.pack(); - return composite; - } - - @Override - protected void createButtonsForButtonBar(Composite parent) { - super.createButtonsForButtonBar(parent); - Button test = createButton(parent, 2, "Test", false); - test.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -1829962269440419560L; - - public void widgetSelected(SelectionEvent arg0) { - testConnection(); - } - }); - } - - void testConnection() { - Session session = null; - try { - URI checkedUri = new URI(uri.getText()); - String checkedUriStr = checkedUri.toString(); - - Hashtable params = new Hashtable(); - params.put(CmsConstants.LABELED_URI, checkedUriStr); - Repository repository = repositoryFactory.getRepository(params); - if (username.getText().trim().equals("")) {// anonymous - // FIXME make it more generic - session = repository.login(CmsConstants.SYS_WORKSPACE); - } else { - // FIXME use getTextChars() when upgrading to 3.7 - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412 - char[] pwd = password.getText().toCharArray(); - SimpleCredentials sc = new SimpleCredentials(username.getText(), pwd); - session = repository.login(sc, "main"); - MessageDialog.openInformation(getParentShell(), "Success", - "Connection to '" + uri.getText() + "' successful"); - } - } catch (Exception e) { - ErrorFeedback.show("Connection test failed for " + uri.getText(), e); - } finally { - JcrUtils.logoutQuietly(session); - } - } - - @Override - protected void okPressed() { - Session nodeSession = null; - try { - nodeSession = nodeRepository.login(); - Node home = CmsJcrUtils.getUserHome(nodeSession); - - Node remote = home.hasNode(ArgeoNames.ARGEO_REMOTE) ? home.getNode(ArgeoNames.ARGEO_REMOTE) - : home.addNode(ArgeoNames.ARGEO_REMOTE); - if (remote.hasNode(name.getText())) - throw new EclipseUiException("There is already a remote repository named " + name.getText()); - Node remoteRepository = remote.addNode(name.getText(), ArgeoTypes.ARGEO_REMOTE_REPOSITORY); - remoteRepository.setProperty(ArgeoNames.ARGEO_URI, uri.getText()); - remoteRepository.setProperty(ArgeoNames.ARGEO_USER_ID, username.getText()); - nodeSession.save(); - if (saveInKeyring.getSelection()) { - String pwdPath = remoteRepository.getPath() + '/' + ArgeoNames.ARGEO_PASSWORD; - keyring.set(pwdPath, password.getText().toCharArray()); - } - nodeSession.save(); - MessageDialog.openInformation(getParentShell(), "Repository Added", - "Remote repository '" + username.getText() + "@" + uri.getText() + "' added"); - - super.okPressed(); - } catch (Exception e) { - ErrorFeedback.show("Cannot add remote repository", e); - } finally { - JcrUtils.logoutQuietly(nodeSession); - } - } - - /** Creates label and text. */ - protected Text createLT(Composite parent, String label, String initial) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - text.setText(initial); - return text; - } - - /** Creates label and check. */ - protected Button createLC(Composite parent, String label, Boolean initial) { - new Label(parent, SWT.NONE).setText(label); - Button check = new Button(parent, SWT.CHECK); - check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - check.setSelection(initial); - return check; - } - - protected Text createLP(Composite parent, String label) { - new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER | SWT.PASSWORD); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - return text; - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java deleted file mode 100644 index b8de06b46..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.argeo.cms.e4.jcr.handlers; - -import java.util.List; - -import javax.inject.Named; -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.e4.jcr.JcrBrowserView; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.argeo.cms.ux.widgets.TreeParent; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; - -/** - * Delete the selected nodes: both in the JCR repository and in the UI view. - * Warning no check is done, except implementation dependent native checks, - * handle with care. - * - * This handler is still 'hard linked' to a GenericJcrBrowser view to enable - * correct tree refresh when a node is added. This must be corrected in future - * versions. - */ -public class DeleteNodes { - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - List selection = (List) selectionService.getSelection(); - if (selection == null) - return; - - JcrBrowserView view = (JcrBrowserView) part.getObject(); - - // confirmation - StringBuffer buf = new StringBuffer(""); - for (Object o : selection) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) o; - buf.append(sjn.getName()).append(' '); - } - Boolean doRemove = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Confirm deletion", - "Do you want to delete " + buf + "?"); - - // operation - if (doRemove) { - SingleJcrNodeElem ancestor = null; - WorkspaceElem rootAncestor = null; - try { - for (Object obj : selection) { - if (obj instanceof SingleJcrNodeElem) { - // Cache objects - SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; - TreeParent tp = (TreeParent) sjn.getParent(); - Node node = sjn.getNode(); - - // Jcr Remove - node.remove(); - node.getSession().save(); - // UI remove - tp.removeChild(sjn); - - // Check if the parent is the root node - if (tp instanceof WorkspaceElem) - rootAncestor = (WorkspaceElem) tp; - else - ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp); - } - } - if (rootAncestor != null) - view.nodeRemoved(rootAncestor); - else if (ancestor != null) - view.nodeRemoved(ancestor); - } catch (Exception e) { - ErrorFeedback.show("Cannot delete selected node ", e); - } - } - } - - private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) { - try { - if (A == null) - return B == null ? null : B; - // Todo enhanced this method - else - return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot find ancestor", re); - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java deleted file mode 100644 index 036e70ac1..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.argeo.cms.e4.jcr.handlers; - -import java.util.List; - -import javax.inject.Named; - -import org.argeo.cms.e4.jcr.JcrBrowserView; -import org.argeo.cms.ui.jcr.JcrBrowserUtils; -import org.argeo.cms.ux.widgets.TreeParent; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; - -/** - * Force the selected objects of the active view to be refreshed doing the - * following: - *

    - *
  1. The model objects are recomputed
  2. - *
  3. the view is refreshed
  4. - *
- */ -public class Refresh { - - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, EPartService partService, - ESelectionService selectionService) { - - JcrBrowserView view = (JcrBrowserView) part.getObject(); - List selection = (List) selectionService.getSelection(); - - if (selection != null && !selection.isEmpty()) { - for (Object obj : selection) - if (obj instanceof TreeParent) { - TreeParent tp = (TreeParent) obj; - JcrBrowserUtils.forceRefreshIfNeeded(tp); - view.refresh(obj); - } - } else if (view instanceof JcrBrowserView) - view.refresh(null); // force full refresh - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/RenameNode.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/RenameNode.java deleted file mode 100644 index 97674abc2..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/RenameNode.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.argeo.cms.e4.jcr.handlers; - -import java.util.List; - -import javax.inject.Named; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.cms.e4.jcr.JcrBrowserView; -import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.dialogs.SingleValue; -import org.argeo.jcr.JcrUtils; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; - -/** - * Canonically call JCR Session#move(String, String) on the first element - * returned by HandlerUtil#getActiveWorkbenchWindow() - * (...getActivePage().getSelection()), if it is a {@link SingleJcrNodeElem}. - * The user must then fill a new name in and confirm - */ -public class RenameNode { - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, EPartService partService, - ESelectionService selectionService) { - List selection = (List) selectionService.getSelection(); - if (selection == null || selection.size() != 1) - return; - JcrBrowserView view = (JcrBrowserView) part.getObject(); - - Object element = selection.get(0); - if (element instanceof SingleJcrNodeElem) { - SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; - Node node = sjn.getNode(); - Session session = null; - String newName = null; - String oldPath = null; - try { - newName = SingleValue.ask("New node name", "Please provide a new name for [" + node.getName() + "]"); - // TODO sanity check and user feedback - newName = JcrUtils.replaceInvalidChars(newName); - oldPath = node.getPath(); - session = node.getSession(); - session.move(oldPath, JcrUtils.parentPath(oldPath) + "/" + newName); - session.save(); - - // Manually refresh the browser view. Must be enhanced - view.refresh(sjn); - } catch (RepositoryException e) { - throw new EclipseUiException("Unable to rename " + node + " to " + newName, e); - } - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/package-info.java deleted file mode 100644 index 4e075e2b1..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** JCR browser handlers. */ -package org.argeo.cms.e4.jcr.handlers; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/package-info.java deleted file mode 100644 index 3e92fb04d..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** JCR browser perspective. */ -package org.argeo.cms.e4.jcr; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/AbstractOsgiComposite.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/AbstractOsgiComposite.java deleted file mode 100644 index 4fd1d68dc..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/AbstractOsgiComposite.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import java.util.Collection; - -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; - -abstract class AbstractOsgiComposite extends Composite { - private static final long serialVersionUID = -4097415973477517137L; - protected final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - protected final CmsLog log = CmsLog.getLog(getClass()); - - public AbstractOsgiComposite(Composite parent, int style) { - super(parent, style); - parent.setLayout(CmsSwtUtils.noSpaceGridLayout()); - setLayout(CmsSwtUtils.noSpaceGridLayout()); - setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - initUi(style); - } - - protected abstract void initUi(int style); - - protected T getService(Class clazz) { - return bc.getService(bc.getServiceReference(clazz)); - } - - protected Collection> getServiceReferences(Class clazz, String filter) { - try { - return bc.getServiceReferences(clazz, filter); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Filter " + filter + " is invalid", e); - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java deleted file mode 100644 index a536da066..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java +++ /dev/null @@ -1,576 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import static org.eclipse.swt.SWT.RIGHT; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.LinkedHashMap; - -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.cms.swt.CmsException; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.util.CmsLink; -import org.argeo.cms.ui.widgets.EditableImage; -import org.argeo.cms.ui.widgets.Img; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ILazyContentProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -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.custom.ScrolledComposite; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; - -public class Browse implements CmsUiProvider { - - // Some local constants to experiment. should be cleaned - private final static String BROWSE_PREFIX = "browse#"; - private final static int THUMBNAIL_WIDTH = 400; - private final static int COLUMN_WIDTH = 160; - private DateFormat timeFormatter = new SimpleDateFormat("dd-MM-yyyy', 'HH:mm"); - - // keep a cache of the opened nodes - // Key is the path - private LinkedHashMap browserCols = new LinkedHashMap(); - private Composite nodeDisplayParent; - private Composite colViewer; - private ScrolledComposite scrolledCmp; - private Text parentPathTxt; - private Text filterTxt; - private Node currEdited; - - private String initialPath; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - if (context == null) - // return null; - throw new CmsException("Context cannot be null"); - GridLayout layout = CmsSwtUtils.noSpaceGridLayout(); - layout.numColumns = 2; - parent.setLayout(layout); - - // Left - Composite leftCmp = new Composite(parent, SWT.NO_FOCUS); - leftCmp.setLayoutData(CmsSwtUtils.fillAll()); - createBrowserPart(leftCmp, context); - - // Right - nodeDisplayParent = new Composite(parent, SWT.NO_FOCUS | SWT.BORDER); - GridData gd = new GridData(SWT.RIGHT, SWT.FILL, false, true); - gd.widthHint = THUMBNAIL_WIDTH; - nodeDisplayParent.setLayoutData(gd); - createNodeView(nodeDisplayParent, context); - - // INIT - setEdited(context); - initialPath = context.getPath(); - - // Workaround we don't yet manage the delete to display parent of the - // initial context node - - return null; - } - - private void createBrowserPart(Composite parent, Node context) throws RepositoryException { - GridLayout layout = CmsSwtUtils.noSpaceGridLayout(); - parent.setLayout(layout); - Composite filterCmp = new Composite(parent, SWT.NO_FOCUS); - filterCmp.setLayoutData(CmsSwtUtils.fillWidth()); - - // top filter - addFilterPanel(filterCmp); - - // scrolled composite - scrolledCmp = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.BORDER | SWT.NO_FOCUS); - scrolledCmp.setLayoutData(CmsSwtUtils.fillAll()); - scrolledCmp.setExpandVertical(true); - scrolledCmp.setExpandHorizontal(true); - scrolledCmp.setShowFocusedControl(true); - - colViewer = new Composite(scrolledCmp, SWT.NO_FOCUS); - scrolledCmp.setContent(colViewer); - scrolledCmp.addControlListener(new ControlAdapter() { - private static final long serialVersionUID = 6589392045145698201L; - - @Override - public void controlResized(ControlEvent e) { - Rectangle r = scrolledCmp.getClientArea(); - scrolledCmp.setMinSize(colViewer.computeSize(SWT.DEFAULT, r.height)); - } - }); - initExplorer(colViewer, context); - } - - private Control initExplorer(Composite parent, Node context) throws RepositoryException { - parent.setLayout(CmsSwtUtils.noSpaceGridLayout()); - createBrowserColumn(parent, context); - return null; - } - - private Control createBrowserColumn(Composite parent, Node context) throws RepositoryException { - // TODO style is not correctly managed. - FilterEntitiesVirtualTable table = new FilterEntitiesVirtualTable(parent, SWT.BORDER | SWT.NO_FOCUS, context); - // CmsUiUtils.style(table, ArgeoOrgStyle.browserColumn.style()); - table.filterList("*"); - table.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true)); - browserCols.put(context.getPath(), table); - return null; - } - - public void addFilterPanel(Composite parent) { - - parent.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(2, false))); - - // Text Area for the filter - parentPathTxt = new Text(parent, SWT.NO_FOCUS); - parentPathTxt.setEditable(false); - filterTxt = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL); - filterTxt.setMessage("Filter current list"); - filterTxt.setLayoutData(CmsSwtUtils.fillWidth()); - filterTxt.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = 7709303319740056286L; - - public void modifyText(ModifyEvent event) { - modifyFilter(false); - } - }); - - filterTxt.addKeyListener(new KeyListener() { - private static final long serialVersionUID = -4523394262771183968L; - - @Override - public void keyReleased(KeyEvent e) { - } - - @Override - public void keyPressed(KeyEvent e) { - boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0; - // boolean altPressed = (e.stateMask & SWT.ALT) != 0; - FilterEntitiesVirtualTable currTable = null; - if (currEdited != null) { - FilterEntitiesVirtualTable table = browserCols.get(getPath(currEdited)); - if (table != null && !table.isDisposed()) - currTable = table; - } - - try { - if (e.keyCode == SWT.ARROW_DOWN) - currTable.setFocus(); - else if (e.keyCode == SWT.BS) { - if (filterTxt.getText().equals("") - && !(getPath(currEdited).equals("/") || getPath(currEdited).equals(initialPath))) { - setEdited(currEdited.getParent()); - e.doit = false; - filterTxt.setFocus(); - } - } else if (e.keyCode == SWT.TAB && !shiftPressed) { - if (currEdited.getNodes(filterTxt.getText() + "*").getSize() == 1) { - setEdited(currEdited.getNodes(filterTxt.getText() + "*").nextNode()); - } - filterTxt.setFocus(); - e.doit = false; - } - } catch (RepositoryException e1) { - throw new CmsException("Unexpected error in key management for " + currEdited + "with filter " - + filterTxt.getText(), e1); - } - - } - }); - } - - private void setEdited(Node node) { - try { - currEdited = node; - CmsSwtUtils.clear(nodeDisplayParent); - createNodeView(nodeDisplayParent, currEdited); - nodeDisplayParent.layout(); - refreshFilters(node); - refreshBrowser(node); - } catch (RepositoryException re) { - throw new CmsException("Unable to update browser for " + node, re); - } - } - - private void refreshFilters(Node node) throws RepositoryException { - String currNodePath = node.getPath(); - parentPathTxt.setText(currNodePath); - filterTxt.setText(""); - filterTxt.getParent().layout(); - } - - private void refreshBrowser(Node node) throws RepositoryException { - - // Retrieve - String currNodePath = node.getPath(); - String currParPath = ""; - if (!"/".equals(currNodePath)) - currParPath = JcrUtils.parentPath(currNodePath); - if ("".equals(currParPath)) - currParPath = "/"; - - Object[][] colMatrix = new Object[browserCols.size()][2]; - - int i = 0, j = -1, k = -1; - for (String path : browserCols.keySet()) { - colMatrix[i][0] = path; - colMatrix[i][1] = browserCols.get(path); - if (j >= 0 && k < 0 && !currNodePath.equals("/")) { - boolean leaveOpened = path.startsWith(currNodePath); - - // workaround for same name siblings - // fix me weird side effect when we go left or click on anb - // already selected, unfocused node - if (leaveOpened && (path.lastIndexOf("/") == 0 && currNodePath.lastIndexOf("/") == 0 - || JcrUtils.parentPath(path).equals(JcrUtils.parentPath(currNodePath)))) - leaveOpened = JcrUtils.lastPathElement(path).equals(JcrUtils.lastPathElement(currNodePath)); - - if (!leaveOpened) - k = i; - } - if (currParPath.equals(path)) - j = i; - i++; - } - - if (j >= 0 && k >= 0) - // remove useless cols - for (int l = i - 1; l >= k; l--) { - browserCols.remove(colMatrix[l][0]); - ((FilterEntitiesVirtualTable) colMatrix[l][1]).dispose(); - } - - // Remove disposed columns - // TODO investigate and fix the mechanism that leave them there after - // disposal - if (browserCols.containsKey(currNodePath)) { - FilterEntitiesVirtualTable currCol = browserCols.get(currNodePath); - if (currCol.isDisposed()) - browserCols.remove(currNodePath); - } - - if (!browserCols.containsKey(currNodePath)) - createBrowserColumn(colViewer, node); - - colViewer.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(browserCols.size(), false))); - // colViewer.pack(); - colViewer.layout(); - // also resize the scrolled composite - scrolledCmp.layout(); - scrolledCmp.getShowFocusedControl(); - // colViewer.getParent().layout(); - // if (JcrUtils.parentPath(currNodePath).equals(currBrowserKey)) { - // } else { - // } - } - - private void modifyFilter(boolean fromOutside) { - if (!fromOutside) - if (currEdited != null) { - String filter = filterTxt.getText() + "*"; - FilterEntitiesVirtualTable table = browserCols.get(getPath(currEdited)); - if (table != null && !table.isDisposed()) - table.filterList(filter); - } - - } - - private String getPath(Node node) { - try { - return node.getPath(); - } catch (RepositoryException e) { - throw new CmsException("Unable to get path for node " + node, e); - } - } - - private Cms2DSize imageWidth = new Cms2DSize(250, 0); - - /** - * Recreates the content of the box that displays information about the current - * selected node. - */ - private Control createNodeView(Composite parent, Node context) throws RepositoryException { - - parent.setLayout(new GridLayout(2, false)); - - if (isImg(context)) { - EditableImage image = new Img(parent, RIGHT, context, imageWidth); - image.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 2, 1)); - } - - // Name and primary type - Label contextL = new Label(parent, SWT.NONE); - CmsSwtUtils.markup(contextL); - contextL.setText("" + context.getName() + ""); - new Label(parent, SWT.NONE).setText(context.getPrimaryNodeType().getName()); - - // Children - for (NodeIterator nIt = context.getNodes(); nIt.hasNext();) { - Node child = nIt.nextNode(); - new CmsLink(child.getName(), BROWSE_PREFIX + child.getPath()).createUi(parent, context); - new Label(parent, SWT.NONE).setText(child.getPrimaryNodeType().getName()); - } - - // Properties - for (PropertyIterator pIt = context.getProperties(); pIt.hasNext();) { - Property property = pIt.nextProperty(); - Label label = new Label(parent, SWT.NONE); - label.setText(property.getName()); - label.setToolTipText(JcrUtils.getPropertyDefinitionAsString(property)); - new Label(parent, SWT.NONE).setText(getPropAsString(property)); - } - - return null; - } - - private boolean isImg(Node node) throws RepositoryException { - // TODO support images - return false; -// return node.hasNode(JCR_CONTENT) && node.isNodeType(CmsTypes.CMS_IMAGE); - } - - private String getPropAsString(Property property) throws RepositoryException { - String result = ""; - if (property.isMultiple()) { - result = getMultiAsString(property, ", "); - } else { - Value value = property.getValue(); - if (value.getType() == PropertyType.BINARY) - result = ""; - else if (value.getType() == PropertyType.DATE) - result = timeFormatter.format(value.getDate().getTime()); - else - result = value.getString(); - } - return result; - } - - private String getMultiAsString(Property property, String separator) throws RepositoryException { - if (separator == null) - separator = "; "; - Value[] values = property.getValues(); - StringBuilder builder = new StringBuilder(); - for (Value val : values) { - String currStr = val.getString(); - if (!"".equals(currStr.trim())) - builder.append(currStr).append(separator); - } - if (builder.lastIndexOf(separator) >= 0) - return builder.substring(0, builder.length() - separator.length()); - else - return builder.toString(); - } - - /** Almost canonical implementation of a table that display entities */ - private class FilterEntitiesVirtualTable extends Composite { - private static final long serialVersionUID = 8798147431706283824L; - - // Context - private Node context; - - // UI Objects - private TableViewer entityViewer; - - // enable management of multiple columns - Node getNode() { - return context; - } - - @Override - public boolean setFocus() { - if (entityViewer.getTable().isDisposed()) - return false; - if (entityViewer.getSelection().isEmpty()) { - Object first = entityViewer.getElementAt(0); - if (first != null) { - entityViewer.setSelection(new StructuredSelection(first), true); - } - } - return entityViewer.getTable().setFocus(); - } - - void filterList(String filter) { - try { - NodeIterator nit = context.getNodes(filter); - refreshFilteredList(nit); - } catch (RepositoryException e) { - throw new CmsException("Unable to filter " + getNode() + " children with filter " + filter, e); - } - - } - - public FilterEntitiesVirtualTable(Composite parent, int style, Node context) { - super(parent, SWT.NO_FOCUS); - this.context = context; - populate(); - } - - protected void populate() { - Composite parent = this; - GridLayout layout = CmsSwtUtils.noSpaceGridLayout(); - - this.setLayout(layout); - createTableViewer(parent); - } - - private void createTableViewer(final Composite parent) { - // the list - // We must limit the size of the table otherwise the full list is - // loaded - // before the layout happens - Composite listCmp = new Composite(parent, SWT.NO_FOCUS); - GridData gd = new GridData(SWT.LEFT, SWT.FILL, false, true); - gd.widthHint = COLUMN_WIDTH; - listCmp.setLayoutData(gd); - listCmp.setLayout(CmsSwtUtils.noSpaceGridLayout()); - - entityViewer = new TableViewer(listCmp, SWT.VIRTUAL | SWT.SINGLE); - Table table = entityViewer.getTable(); - - table.setLayoutData(CmsSwtUtils.fillAll()); - table.setLinesVisible(true); - table.setHeaderVisible(false); - CmsSwtUtils.markup(table); - - CmsSwtUtils.style(table, MaintenanceStyles.BROWSER_COLUMN); - - // first column - TableViewerColumn column = new TableViewerColumn(entityViewer, SWT.NONE); - TableColumn tcol = column.getColumn(); - tcol.setWidth(COLUMN_WIDTH); - tcol.setResizable(true); - column.setLabelProvider(new SimpleNameLP()); - - entityViewer.setContentProvider(new MyLazyCP(entityViewer)); - entityViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) entityViewer.getSelection(); - if (selection.isEmpty()) - return; - else - setEdited((Node) selection.getFirstElement()); - - } - }); - - table.addKeyListener(new KeyListener() { - private static final long serialVersionUID = -330694313896036230L; - - @Override - public void keyReleased(KeyEvent e) { - } - - @Override - public void keyPressed(KeyEvent e) { - - IStructuredSelection selection = (IStructuredSelection) entityViewer.getSelection(); - Node selected = null; - if (!selection.isEmpty()) - selected = ((Node) selection.getFirstElement()); - try { - if (e.keyCode == SWT.ARROW_RIGHT) { - if (selected != null) { - setEdited(selected); - browserCols.get(selected.getPath()).setFocus(); - } - } else if (e.keyCode == SWT.ARROW_LEFT) { - try { - selected = getNode().getParent(); - String newPath = selected.getPath(); // getNode().getParent() - setEdited(selected); - if (browserCols.containsKey(newPath)) - browserCols.get(newPath).setFocus(); - } catch (ItemNotFoundException ie) { - // root silent - } - } - } catch (RepositoryException ie) { - throw new CmsException("Error while managing arrow " + "events in the browser for " + selected, - ie); - } - } - }); - } - - private class MyLazyCP implements ILazyContentProvider { - private static final long serialVersionUID = 1L; - private TableViewer viewer; - private Object[] elements; - - public MyLazyCP(TableViewer viewer) { - this.viewer = viewer; - } - - public void dispose() { - } - - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // IMPORTANT: don't forget this: an exception will be thrown if - // a selected object is not part of the results anymore. - viewer.setSelection(null); - this.elements = (Object[]) newInput; - } - - public void updateElement(int index) { - viewer.replace(elements[index], index); - } - } - - protected void refreshFilteredList(NodeIterator children) { - Object[] rows = JcrUtils.nodeIteratorToList(children).toArray(); - entityViewer.setInput(rows); - entityViewer.setItemCount(rows.length); - entityViewer.refresh(); - } - - public class SimpleNameLP extends ColumnLabelProvider { - private static final long serialVersionUID = 2465059387875338553L; - - @Override - public String getText(Object element) { - if (element instanceof Node) { - Node curr = ((Node) element); - try { - return curr.getName(); - } catch (RepositoryException e) { - throw new CmsException("Unable to get name for" + curr); - } - } - return super.getText(element); - } - } - } -} \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/ConnectivityDeploymentUi.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/ConnectivityDeploymentUi.java deleted file mode 100644 index 97f3e6713..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/ConnectivityDeploymentUi.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.osgi.framework.ServiceReference; -import org.osgi.service.http.HttpService; -import org.osgi.service.useradmin.UserAdmin; - -class ConnectivityDeploymentUi extends AbstractOsgiComposite { - private static final long serialVersionUID = 590221539553514693L; - - public ConnectivityDeploymentUi(Composite parent, int style) { - super(parent, style); - } - - @Override - protected void initUi(int style) { - StringBuffer text = new StringBuffer(); - text.append("Provided Servers
"); - - ServiceReference userAdminRef = bc.getServiceReference(HttpService.class); - if (userAdminRef != null) { - // FIXME use constants - Object httpPort = userAdminRef.getProperty("http.port"); - Object httpsPort = userAdminRef.getProperty("https.port"); - if (httpPort != null) - text.append("http ").append(httpPort).append("
"); - if (httpsPort != null) - text.append("https ").append(httpsPort).append("
"); - - } - - text.append("
"); - text.append("Referenced Servers
"); - - Label label = new Label(this, SWT.NONE); - label.setData(new GridData(SWT.FILL, SWT.FILL, false, false)); - CmsSwtUtils.markup(label); - label.setText(text.toString()); - } - - protected boolean isDeployed() { - return bc.getServiceReference(UserAdmin.class) != null; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DataDeploymentUi.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DataDeploymentUi.java deleted file mode 100644 index ef95bde64..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DataDeploymentUi.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import java.io.File; -import java.io.IOException; -import java.nio.file.FileStore; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collection; - -import org.apache.jackrabbit.core.RepositoryContext; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.osgi.framework.ServiceReference; - -class DataDeploymentUi extends AbstractOsgiComposite { - private static final long serialVersionUID = 590221539553514693L; - - public DataDeploymentUi(Composite parent, int style) { - super(parent, style); - } - - @Override - protected void initUi(int style) { - if (isDeployed()) { - initCurrentUi(this); - } else { - initNewUi(this); - } - } - - private void initNewUi(Composite parent) { -// try { -// ConfigurationAdmin confAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class)); -// Configuration[] confs = confAdmin.listConfigurations( -// "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + NodeConstants.NODE_REPOS_FACTORY_PID + ")"); -// if (confs == null || confs.length == 0) { -// Group buttonGroup = new Group(parent, SWT.NONE); -// buttonGroup.setText("Repository Type"); -// buttonGroup.setLayout(new GridLayout(2, true)); -// buttonGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL)); -// -// SelectionListener selectionListener = new SelectionAdapter() { -// private static final long serialVersionUID = 6247064348421088092L; -// -// public void widgetSelected(SelectionEvent event) { -// Button radio = (Button) event.widget; -// if (!radio.getSelection()) -// return; -// log.debug(event); -// JackrabbitType nodeType = (JackrabbitType) radio.getData(); -// if (log.isDebugEnabled()) -// log.debug(" selected = " + nodeType.name()); -// }; -// }; -// -// for (JackrabbitType nodeType : JackrabbitType.values()) { -// Button radio = new Button(buttonGroup, SWT.RADIO); -// radio.setText(nodeType.name()); -// radio.setData(nodeType); -// if (nodeType.equals(JackrabbitType.localfs)) -// radio.setSelection(true); -// radio.addSelectionListener(selectionListener); -// } -// -// } else if (confs.length == 1) { -// -// } else { -// throw new CmsException("Multiple repos not yet supported"); -// } -// } catch (Exception e) { -// throw new CmsException("Cannot initialize UI", e); -// } - - } - - private void initCurrentUi(Composite parent) { - parent.setLayout(new GridLayout()); - Collection> contexts = getServiceReferences(RepositoryContext.class, - "(" + CmsConstants.CN + "=*)"); - StringBuffer text = new StringBuffer(); - text.append("Jackrabbit Repositories
"); - for (ServiceReference sr : contexts) { - RepositoryContext repositoryContext = bc.getService(sr); - String alias = sr.getProperty(CmsConstants.CN).toString(); - String rootNodeId = repositoryContext.getRootNodeId().toString(); - RepositoryConfig repositoryConfig = repositoryContext.getRepositoryConfig(); - Path repoHomePath = new File(repositoryConfig.getHomeDir()).toPath().toAbsolutePath(); - // TODO check data store - - text.append("" + alias + "
"); - text.append("rootNodeId: " + rootNodeId + "
"); - try { - FileStore fileStore = Files.getFileStore(repoHomePath); - text.append("partition: " + fileStore.toString() + "
"); - text.append( - percentUsed(fileStore) + " used (" + humanReadable(fileStore.getUsableSpace()) + " free)
"); - } catch (IOException e) { - log.error("Cannot check fileStore for " + repoHomePath, e); - } - } - Label label = new Label(parent, SWT.NONE); - label.setData(new GridData(SWT.FILL, SWT.FILL, false, false)); - CmsSwtUtils.markup(label); - label.setText("" + text.toString() + ""); - } - - private String humanReadable(long bytes) { - long mb = bytes / (1024 * 1024); - return mb >= 2048 ? Long.toString(mb / 1024) + " GB" : Long.toString(mb) + " MB"; - } - - private String percentUsed(FileStore fs) throws IOException { - long used = fs.getTotalSpace() - fs.getUnallocatedSpace(); - long percent = used * 100 / fs.getTotalSpace(); - if (log.isTraceEnabled()) { - // output identical to `df -B 1`) - log.trace(fs.getTotalSpace() + "," + used + "," + fs.getUsableSpace()); - } - String span; - if (percent < 80) - span = ""; - else if (percent < 95) - span = ""; - else - span = ""; - return span + percent + "%"; - } - - protected boolean isDeployed() { - return bc.getServiceReference(RepositoryContext.class) != null; - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java deleted file mode 100644 index 0a28dc5ee..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsContext; -import org.argeo.api.cms.CmsDeployment; -import org.argeo.api.cms.CmsState; -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; - -class DeploymentEntryPoint { - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - protected void createContents(Composite parent) { - // FIXME manage authentication if needed - // if (!CurrentUser.roles().contains(AuthConstants.ROLE_ADMIN)) - // return; - - // parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - if (isDesktop()) { - parent.setLayout(new GridLayout(2, true)); - } else { - // TODO add scrolling - parent.setLayout(new GridLayout(1, true)); - } - - initHighLevelSummary(parent); - - Group securityGroup = createHighLevelGroup(parent, "Security"); - securityGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - new SecurityDeploymentUi(securityGroup, SWT.NONE); - - Group dataGroup = createHighLevelGroup(parent, "Data"); - dataGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - new DataDeploymentUi(dataGroup, SWT.NONE); - - Group logGroup = createHighLevelGroup(parent, "Notifications"); - logGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); - new LogDeploymentUi(logGroup, SWT.NONE); - - Group connectivityGroup = createHighLevelGroup(parent, "Connectivity"); - new ConnectivityDeploymentUi(connectivityGroup, SWT.NONE); - connectivityGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); - - } - - private void initHighLevelSummary(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); - if (isDesktop()) - gridData.horizontalSpan = 3; - composite.setLayoutData(gridData); - composite.setLayout(new FillLayout()); - - ServiceReference nodeStateRef = bc.getServiceReference(CmsState.class); - if (nodeStateRef == null) - throw new IllegalStateException("No CMS state available"); - CmsState nodeState = bc.getService(nodeStateRef); - ServiceReference nodeDeploymentRef = bc.getServiceReference(CmsContext.class); - Label label = new Label(composite, SWT.WRAP); - CmsSwtUtils.markup(label); - if (nodeDeploymentRef == null) { - label.setText("Not yet deployed on, please configure below."); - } else { - Object stateUuid = nodeStateRef.getProperty(CmsConstants.CN); - CmsContext nodeDeployment = bc.getService(nodeDeploymentRef); - GregorianCalendar calendar = new GregorianCalendar(); - calendar.setTimeInMillis(nodeDeployment.getAvailableSince()); - calendar.setTimeZone(TimeZone.getDefault()); - label.setText("Deployment state " + stateUuid + ", available since " + calendar.getTime() + ""); - } - } - - private static Group createHighLevelGroup(Composite parent, String text) { - Group group = new Group(parent, SWT.NONE); - group.setText(text); - CmsSwtUtils.markup(group); - return group; - } - - private boolean isDesktop() { - return true; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/LogDeploymentUi.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/LogDeploymentUi.java deleted file mode 100644 index fa5d3dae3..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/LogDeploymentUi.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Enumeration; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Text; -import org.osgi.service.log.LogEntry; -import org.osgi.service.log.LogListener; -import org.osgi.service.log.LogReaderService; - -class LogDeploymentUi extends AbstractOsgiComposite implements LogListener { - private static final long serialVersionUID = 590221539553514693L; - - private DateFormat dateFormat = new SimpleDateFormat("MMdd HH:mm"); - - private Display display; - private Text logDisplay; - - public LogDeploymentUi(Composite parent, int style) { - super(parent, style); - } - - @Override - protected void initUi(int style) { - LogReaderService logReader = getService(LogReaderService.class); - // FIXME use server push - // logReader.addLogListener(this); - this.display = getDisplay(); - this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - logDisplay = new Text(this, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY); - logDisplay.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - CmsSwtUtils.markup(logDisplay); - Enumeration logEntries = (Enumeration) logReader.getLog(); - while (logEntries.hasMoreElements()) - logDisplay.append(printEntry(logEntries.nextElement())); - } - - private String printEntry(LogEntry entry) { - StringBuilder sb = new StringBuilder(); - GregorianCalendar calendar = new GregorianCalendar(TimeZone.getDefault()); - calendar.setTimeInMillis(entry.getTime()); - sb.append(dateFormat.format(calendar.getTime())).append(' '); - sb.append(entry.getMessage()); - sb.append('\n'); - return sb.toString(); - } - - @Override - public void logged(LogEntry entry) { - if (display.isDisposed()) - return; - display.asyncExec(() -> { - if (logDisplay.isDisposed()) - return; - logDisplay.append(printEntry(entry)); - }); - display.wake(); - } - - // @Override - // public void dispose() { - // super.dispose(); - // getService(LogReaderService.class).removeLogListener(this); - // } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/MaintenanceStyles.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/MaintenanceStyles.java deleted file mode 100644 index df1be51ad..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/MaintenanceStyles.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -/** Specific styles used by the various maintenance pages . */ -public interface MaintenanceStyles { - // General - public final static String PREFIX = "maintenance_"; - - // Browser - public final static String BROWSER_COLUMN = "browser_column"; - } diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/NonAdminPage.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/NonAdminPage.java deleted file mode 100644 index cb38ce899..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/NonAdminPage.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.CmsUiProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; - -public class NonAdminPage implements CmsUiProvider{ - - @Override - public Control createUi(Composite parent, Node context) - throws RepositoryException { - Composite body = new Composite(parent, SWT.NO_FOCUS); - body.setLayoutData(CmsSwtUtils.fillAll()); - body.setLayout(new GridLayout()); - Label label = new Label(body, SWT.NONE); - label.setText("You should be an admin to perform maintenance operations. " - + "Are you sure you are logged in?"); - label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); - return null; - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/SecurityDeploymentUi.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/SecurityDeploymentUi.java deleted file mode 100644 index 3492c5499..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/SecurityDeploymentUi.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.argeo.cms.e4.maintenance; - -import java.net.URI; - -import org.argeo.cms.swt.CmsSwtUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.UserAdmin; - -class SecurityDeploymentUi extends AbstractOsgiComposite { - private static final long serialVersionUID = 590221539553514693L; - - public SecurityDeploymentUi(Composite parent, int style) { - super(parent, style); - } - - @Override - protected void initUi(int style) { - if (isDeployed()) { - initCurrentUi(this); - } else { - initNewUi(this); - } - } - - private void initNewUi(Composite parent) { - new Label(parent, SWT.NONE).setText("Security is not configured"); - } - - private void initCurrentUi(Composite parent) { - ServiceReference userAdminRef = bc.getServiceReference(UserAdmin.class); - UserAdmin userAdmin = bc.getService(userAdminRef); - StringBuffer text = new StringBuffer(); - text.append("Domains
"); - domains: for (String key : userAdminRef.getPropertyKeys()) { - if (!key.startsWith("/")) - continue domains; - URI uri; - try { - uri = new URI(key); - } catch (Exception e) { - // ignore non URI keys - continue domains; - } - - String rootDn = uri.getPath().substring(1, uri.getPath().length()); - // FIXME make reading query options more robust, using utils - boolean readOnly = uri.getQuery().equals("readOnly=true"); - if (readOnly) - text.append(""); - else - text.append(""); - - text.append(rootDn); - text.append("
"); - try { - Role[] roles = userAdmin.getRoles("(dn=*," + rootDn + ")"); - long userCount = 0; - long groupCount = 0; - for (Role role : roles) { - if (role.getType() == Role.USER) - userCount++; - else - groupCount++; - } - text.append(" " + userCount + " users, " + groupCount +" groups.
"); - } catch (InvalidSyntaxException e) { - log.error("Invalid syntax", e); - } - } - Label label = new Label(parent, SWT.NONE); - label.setData(new GridData(SWT.FILL, SWT.FILL, false, false)); - CmsSwtUtils.markup(label); - label.setText(text.toString()); - } - - protected boolean isDeployed() { - return bc.getServiceReference(UserAdmin.class) != null; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/package-info.java deleted file mode 100644 index e4d2ad4c3..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Maintenance perspective. */ -package org.argeo.cms.e4.maintenance; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/AbstractRoleEditor.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/AbstractRoleEditor.java deleted file mode 100644 index 137f76242..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/AbstractRoleEditor.java +++ /dev/null @@ -1,287 +0,0 @@ -package org.argeo.cms.e4.users; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.inject.Inject; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.ui.eclipse.forms.AbstractFormPart; -import org.argeo.cms.ui.eclipse.forms.IManagedForm; -import org.argeo.cms.ui.eclipse.forms.ManagedForm; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.e4.ui.di.Persist; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.osgi.service.useradmin.Authorization; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Editor for a user, might be a user or a group. */ -public abstract class AbstractRoleEditor { - - // public final static String USER_EDITOR_ID = WorkbenchUiPlugin.PLUGIN_ID + - // ".userEditor"; - // public final static String GROUP_EDITOR_ID = WorkbenchUiPlugin.PLUGIN_ID + - // ".groupEditor"; - - /* DEPENDENCY INJECTION */ - @Inject - protected UserAdminWrapper userAdminWrapper; - - @Inject - private MPart mPart; - - // @Inject - // Composite parent; - - private UserAdmin userAdmin; - - // Context - private User user; - private String username; - - private NameChangeListener listener; - - private ManagedForm managedForm; - - // public void init(IEditorSite site, IEditorInput input) throws - // PartInitException { - @PostConstruct - public void init(Composite parent) { - this.userAdmin = userAdminWrapper.getUserAdmin(); - username = mPart.getPersistedState().get(LdapAttrs.uid.name()); - user = (User) userAdmin.getRole(username); - - listener = new NameChangeListener(Display.getCurrent()); - userAdminWrapper.addListener(listener); - updateEditorTitle(null); - - managedForm = new ManagedForm(parent) { - - @Override - public void staleStateChanged() { - refresh(); - } - }; - ScrolledComposite scrolled = managedForm.getForm(); - Composite body = new Composite(scrolled, SWT.NONE); - scrolled.setContent(body); - createUi(body); - managedForm.refresh(); - } - - abstract void createUi(Composite parent); - - /** - * returns the list of all authorizations for the given user or of the current - * displayed user if parameter is null - */ - protected List getFlatGroups(User aUser) { - Authorization currAuth; - if (aUser == null) - currAuth = userAdmin.getAuthorization(this.user); - else - currAuth = userAdmin.getAuthorization(aUser); - - String[] roles = currAuth.getRoles(); - - List groups = new ArrayList(); - for (String roleStr : roles) { - User currRole = (User) userAdmin.getRole(roleStr); - if (currRole != null && !groups.contains(currRole)) - groups.add(currRole); - } - return groups; - } - - protected IManagedForm getManagedForm() { - return managedForm; - } - - /** Exposes the user (or group) that is displayed by the current editor */ - protected User getDisplayedUser() { - return user; - } - - private void setDisplayedUser(User user) { - this.user = user; - } - - void updateEditorTitle(String title) { - if (title == null) { - String commonName = UserAdminUtils.getProperty(user, LdapAttrs.cn.name()); - title = "".equals(commonName) ? user.getName() : commonName; - } - setPartName(title); - } - - protected void setPartName(String name) { - mPart.setLabel(name); - } - - // protected void addPages() { - // try { - // if (user.getType() == Role.GROUP) - // addPage(new GroupMainPage(this, userAdminWrapper, repository, nodeInstance)); - // else - // addPage(new UserMainPage(this, userAdminWrapper)); - // } catch (Exception e) { - // throw new CmsException("Cannot add pages", e); - // } - // } - - @Persist - public void doSave(IProgressMonitor monitor) { - userAdminWrapper.beginTransactionIfNeeded(); - commitPages(true); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - // firePropertyChange(PROP_DIRTY); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, user)); - } - - protected void commitPages(boolean b) { - managedForm.commit(b); - } - - @PreDestroy - public void dispose() { - userAdminWrapper.removeListener(listener); - managedForm.dispose(); - } - - // CONTROLERS FOR THIS EDITOR AND ITS PAGES - - class NameChangeListener extends UiUserAdminListener { - public NameChangeListener(Display display) { - super(display); - } - - @Override - public void roleChangedToUiThread(UserAdminEvent event) { - Role changedRole = event.getRole(); - if (changedRole == null || changedRole.equals(user)) { - updateEditorTitle(null); - User reloadedUser = (User) userAdminWrapper.getUserAdmin().getRole(user.getName()); - setDisplayedUser(reloadedUser); - } - } - } - - class MainInfoListener extends UiUserAdminListener { - private final AbstractFormPart part; - - public MainInfoListener(Display display, AbstractFormPart part) { - super(display); - this.part = part; - } - - @Override - public void roleChangedToUiThread(UserAdminEvent event) { - // Rollback - if (event.getRole() == null) - part.markStale(); - } - } - - class GroupChangeListener extends UiUserAdminListener { - private final AbstractFormPart part; - - public GroupChangeListener(Display display, AbstractFormPart part) { - super(display); - this.part = part; - } - - @Override - public void roleChangedToUiThread(UserAdminEvent event) { - // always mark as stale - part.markStale(); - } - } - - /** Registers a listener that will notify this part */ - class FormPartML implements ModifyListener { - private static final long serialVersionUID = 6299808129505381333L; - private AbstractFormPart formPart; - - public FormPartML(AbstractFormPart generalPart) { - this.formPart = generalPart; - } - - public void modifyText(ModifyEvent e) { - // Discard event when the control does not have the focus, typically - // to avoid all editors being marked as dirty during a Rollback - if (((Control) e.widget).isFocusControl()) - formPart.markDirty(); - } - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } - - /** Creates label and multiline text. */ - Text createLMT(Composite parent, String label, String value) { - Label lbl = new Label(parent, SWT.NONE); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - Text text = new Text(parent, SWT.NONE); - text.setText(value); - text.setLayoutData(new GridData(SWT.LEAD, SWT.FILL, true, true)); - return text; - } - - /** Creates label and password. */ - Text createLP(Composite parent, String label, String value) { - Label lbl = new Label(parent, SWT.NONE); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - Text text = new Text(parent, SWT.PASSWORD | SWT.BORDER); - text.setText(value); - text.setLayoutData(new GridData(SWT.LEAD, SWT.FILL, true, false)); - return text; - } - - /** Creates label and text. */ - Text createLT(Composite parent, String label, String value) { - Label lbl = new Label(parent, SWT.NONE); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - lbl.setFont(EclipseUiUtils.getBoldFont(parent)); - Text text = new Text(parent, SWT.BORDER); - text.setText(value); - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT); - return text; - } - - Text createReadOnlyLT(Composite parent, String label, String value) { - Label lbl = new Label(parent, SWT.NONE); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - lbl.setFont(EclipseUiUtils.getBoldFont(parent)); - Text text = new Text(parent, SWT.NONE); - text.setText(value); - text.setLayoutData(new GridData(SWT.LEAD, SWT.FILL, true, false)); - text.setEditable(false); - // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT); - return text; - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/CmsWorkbenchStyles.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/CmsWorkbenchStyles.java deleted file mode 100644 index 07df312e1..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/CmsWorkbenchStyles.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.cms.e4.users; - -/** Centralize the declaration of Workbench specific CSS Styles */ -interface CmsWorkbenchStyles { - - // Specific People layouting - String WORKBENCH_FORM_TEXT = "workbench_form_text"; -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupEditor.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupEditor.java deleted file mode 100644 index d54f8bc38..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupEditor.java +++ /dev/null @@ -1,566 +0,0 @@ -package org.argeo.cms.e4.users; - -import static org.argeo.api.cms.CmsContext.WORKGROUP; -import static org.argeo.cms.auth.UserAdminUtils.setProperty; -import static org.argeo.util.naming.LdapAttrs.businessCategory; -import static org.argeo.util.naming.LdapAttrs.description; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.annotation.PreDestroy; -import javax.inject.Inject; -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsContext; -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.providers.CommonNameLP; -import org.argeo.cms.e4.users.providers.MailLP; -import org.argeo.cms.e4.users.providers.RoleIconLP; -import org.argeo.cms.e4.users.providers.UserFilter; -import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.eclipse.forms.AbstractFormPart; -import org.argeo.cms.ui.eclipse.forms.IManagedForm; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.argeo.util.naming.LdapAttrs; -import org.argeo.util.transaction.WorkTransaction; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.ViewerDropAdapter; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.dnd.TransferData; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.Role; -//import org.eclipse.ui.forms.AbstractFormPart; -//import org.eclipse.ui.forms.IManagedForm; -//import org.eclipse.ui.forms.SectionPart; -//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; -//import org.eclipse.ui.forms.widgets.Section; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Display/edit main properties of a given group */ -public class GroupEditor extends AbstractRoleEditor { - // final static String ID = "GroupEditor.mainPage"; - - @Inject - private EPartService partService; - - // private final UserEditor editor; - @Inject - private Repository repository; - @Inject - private CmsContext nodeInstance; - // private final UserAdminWrapper userAdminWrapper; - private Session groupsSession; - - // public GroupMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper, - // Repository repository, - // NodeInstance nodeInstance) { - // super(editor, ID, "Main"); - // try { - // session = repository.login(); - // } catch (RepositoryException e) { - // throw new CmsException("Cannot retrieve session of in MainGroupPage - // constructor", e); - // } - // this.editor = (UserEditor) editor; - // this.userAdminWrapper = userAdminWrapper; - // this.nodeInstance = nodeInstance; - // } - - // protected void createFormContent(final IManagedForm mf) { - // ScrolledForm form = mf.getForm(); - // Composite body = form.getBody(); - // GridLayout mainLayout = new GridLayout(); - // body.setLayout(mainLayout); - // Group group = (Group) editor.getDisplayedUser(); - // appendOverviewPart(body, group); - // appendMembersPart(body, group); - // } - - @Override - protected void createUi(Composite parent) { - try { - groupsSession = repository.login(CmsConstants.SRV_WORKSPACE); - } catch (RepositoryException e) { - throw new JcrException("Cannot retrieve session", e); - } - // ScrolledForm form = mf.getForm(); - // Composite body = form.getBody(); - // Composite body = new Composite(parent, SWT.NONE); - Composite body = parent; - GridLayout mainLayout = new GridLayout(); - body.setLayout(mainLayout); - Group group = (Group) getDisplayedUser(); - appendOverviewPart(body, group); - appendMembersPart(body, group); - } - - @PreDestroy - public void dispose() { - JcrUtils.logoutQuietly(groupsSession); - super.dispose(); - } - - /** Creates the general section */ - protected void appendOverviewPart(final Composite parent, final Group group) { - Composite body = new Composite(parent, SWT.NONE); - // GridLayout layout = new GridLayout(5, false); - GridLayout layout = new GridLayout(2, false); - body.setLayout(layout); - body.setLayoutData(CmsSwtUtils.fillWidth()); - - String cn = UserAdminUtils.getProperty(group, LdapAttrs.cn.name()); - createReadOnlyLT(body, "Name", cn); - createReadOnlyLT(body, "DN", group.getName()); - createReadOnlyLT(body, "Domain", UserAdminUtils.getDomainName(group)); - - // Description - Label descLbl = new Label(body, SWT.LEAD); - descLbl.setFont(EclipseUiUtils.getBoldFont(body)); - descLbl.setText("Description"); - descLbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false, 2, 1)); - final Text descTxt = new Text(body, SWT.LEAD | SWT.MULTI | SWT.WRAP | SWT.BORDER); - GridData gd = EclipseUiUtils.fillWidth(); - gd.heightHint = 50; - gd.horizontalSpan = 2; - descTxt.setLayoutData(gd); - - // Mark as workgroup - Link markAsWorkgroupLk = new Link(body, SWT.NONE); - markAsWorkgroupLk.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); - - // create form part (controller) - final AbstractFormPart part = new AbstractFormPart() { - - private MainInfoListener listener; - - @Override - public void initialize(IManagedForm form) { - super.initialize(form); - listener = new MainInfoListener(parent.getDisplay(), this); - userAdminWrapper.addListener(listener); - } - - @Override - public void dispose() { - userAdminWrapper.removeListener(listener); - super.dispose(); - } - - public void commit(boolean onSave) { - // group.getProperties().put(LdapAttrs.description.name(), descTxt.getText()); - setProperty(group, description, descTxt.getText()); - super.commit(onSave); - } - - @Override - public void refresh() { - // dnTxt.setText(group.getName()); - // cnTxt.setText(UserAdminUtils.getProperty(group, LdapAttrs.cn.name())); - descTxt.setText(UserAdminUtils.getProperty(group, LdapAttrs.description.name())); - Node workgroupHome = CmsJcrUtils.getGroupHome(groupsSession, cn); - if (workgroupHome == null) - markAsWorkgroupLk.setText("Mark as workgroup"); - else - markAsWorkgroupLk.setText("Configured as workgroup"); - parent.layout(true, true); - super.refresh(); - } - }; - - markAsWorkgroupLk.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -6439340898096365078L; - - @Override - public void widgetSelected(SelectionEvent e) { - - boolean confirmed = MessageDialog.openConfirm(parent.getShell(), "Mark as workgroup", - "Are you sure you want to mark " + cn + " as being a workgroup? "); - if (confirmed) { - Node workgroupHome = CmsJcrUtils.getGroupHome(groupsSession, cn); - if (workgroupHome != null) - return; // already marked as workgroup, do nothing - else { - // improve transaction management - userAdminWrapper.beginTransactionIfNeeded(); - nodeInstance.createWorkgroup(group.getName()); - setProperty(group, businessCategory, WORKGROUP); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group)); - part.refresh(); - } - } - } - }); - - ModifyListener defaultListener = new FormPartML(part); - descTxt.addModifyListener(defaultListener); - getManagedForm().addPart(part); - } - - /** Filtered table with members. Has drag and drop ability */ - protected void appendMembersPart(Composite parent, Group group) { - // Section section = tk.createSection(parent, Section.TITLE_BAR); - // section.setText("Members"); - // section.setLayoutData(EclipseUiUtils.fillAll()); - - Composite body = new Composite(parent, SWT.BORDER); - body.setLayout(new GridLayout()); - // section.setClient(body); - body.setLayoutData(EclipseUiUtils.fillAll()); - - // Define the displayed columns - List columnDefs = new ArrayList(); - columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24)); - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150)); - columnDefs.add(new ColumnDefinition(new MailLP(), "Mail", 150)); - // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name", - // 240)); - - // Create and configure the table - LdifUsersTable userViewerCmp = new MyUserTableViewer(body, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, - userAdminWrapper.getUserAdmin()); - - userViewerCmp.setColumnDefinitions(columnDefs); - userViewerCmp.populate(true, false); - userViewerCmp.setLayoutData(EclipseUiUtils.fillAll()); - - // Controllers - TableViewer userViewer = userViewerCmp.getTableViewer(); - userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService)); - int operations = DND.DROP_COPY | DND.DROP_MOVE; - Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; - userViewer.addDropSupport(operations, tt, - new GroupDropListener(userAdminWrapper, userViewerCmp, (Group) getDisplayedUser())); - - AbstractFormPart part = new GroupMembersPart(userViewerCmp); - getManagedForm().addPart(part); - - // remove button - // addRemoveAbility(toolBarManager, userViewerCmp.getTableViewer(), group); - Action action = new RemoveMembershipAction(userViewer, group, "Remove selected items from this group", - SecurityAdminImages.ICON_REMOVE_DESC); - - ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); - ToolBar toolBar = toolBarManager.createControl(body); - toolBar.setLayoutData(CmsSwtUtils.fillWidth()); - - toolBarManager.add(action); - toolBarManager.update(true); - - } - - // private LdifUsersTable createMemberPart(Composite parent, Group group) { - // - // // Define the displayed columns - // List columnDefs = new ArrayList(); - // columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24)); - // columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150)); - // columnDefs.add(new ColumnDefinition(new MailLP(), "Mail", 150)); - // // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished - // Name", - // // 240)); - // - // // Create and configure the table - // LdifUsersTable userViewerCmp = new MyUserTableViewer(parent, SWT.MULTI | - // SWT.H_SCROLL | SWT.V_SCROLL, - // userAdminWrapper.getUserAdmin()); - // - // userViewerCmp.setColumnDefinitions(columnDefs); - // userViewerCmp.populate(true, false); - // userViewerCmp.setLayoutData(EclipseUiUtils.fillAll()); - // - // // Controllers - // TableViewer userViewer = userViewerCmp.getTableViewer(); - // userViewer.addDoubleClickListener(new - // UserTableDefaultDClickListener(partService)); - // int operations = DND.DROP_COPY | DND.DROP_MOVE; - // Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; - // userViewer.addDropSupport(operations, tt, - // new GroupDropListener(userAdminWrapper, userViewerCmp, (Group) - // getDisplayedUser())); - // - // // userViewerCmp.refresh(); - // return userViewerCmp; - // } - - // Local viewers - private class MyUserTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 8467999509931900367L; - - private final UserFilter userFilter; - - public MyUserTableViewer(Composite parent, int style, UserAdmin userAdmin) { - super(parent, style, true); - userFilter = new UserFilter(); - - } - - @Override - protected List listFilteredElements(String filter) { - // reload user and set it in the editor - Group group = (Group) getDisplayedUser(); - Role[] roles = group.getMembers(); - List users = new ArrayList(); - userFilter.setSearchText(filter); - // userFilter.setShowSystemRole(true); - for (Role role : roles) - // if (role.getType() == Role.GROUP) - if (userFilter.select(null, null, role)) - users.add((User) role); - return users; - } - } - - // private void addRemoveAbility(ToolBarManager toolBarManager, TableViewer - // userViewer, Group group) { - // // Section section = sectionPart.getSection(); - // // ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); - // // ToolBar toolbar = toolBarManager.createControl(parent); - // // ToolBar toolbar = toolBarManager.getControl(); - // // final Cursor handCursor = new Cursor(toolbar.getDisplay(), - // SWT.CURSOR_HAND); - // // toolbar.setCursor(handCursor); - // // toolbar.addDisposeListener(new DisposeListener() { - // // private static final long serialVersionUID = 3882131405820522925L; - // // - // // public void widgetDisposed(DisposeEvent e) { - // // if ((handCursor != null) && (handCursor.isDisposed() == false)) { - // // handCursor.dispose(); - // // } - // // } - // // }); - // - // Action action = new RemoveMembershipAction(userViewer, group, "Remove - // selected items from this group", - // SecurityAdminImages.ICON_REMOVE_DESC); - // toolBarManager.add(action); - // toolBarManager.update(true); - // // section.setTextClient(toolbar); - // } - - private class RemoveMembershipAction extends Action { - private static final long serialVersionUID = -1337713097184522588L; - - private final TableViewer userViewer; - private final Group group; - - RemoveMembershipAction(TableViewer userViewer, Group group, String name, ImageDescriptor img) { - super(name, img); - this.userViewer = userViewer; - this.group = group; - } - - @Override - public void run() { - ISelection selection = userViewer.getSelection(); - if (selection.isEmpty()) - return; - - @SuppressWarnings("unchecked") - Iterator it = ((IStructuredSelection) selection).iterator(); - List users = new ArrayList(); - while (it.hasNext()) { - User currUser = it.next(); - users.add(currUser); - } - - userAdminWrapper.beginTransactionIfNeeded(); - for (User user : users) { - group.removeMember(user); - } - userAdminWrapper.commitOrNotifyTransactionStateChange(); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group)); - } - } - - // LOCAL CONTROLLERS - private class GroupMembersPart extends AbstractFormPart { - private final LdifUsersTable userViewer; - // private final Group group; - - private GroupChangeListener listener; - - public GroupMembersPart(LdifUsersTable userViewer) { - // super(section); - this.userViewer = userViewer; - // this.group = group; - } - - @Override - public void initialize(IManagedForm form) { - super.initialize(form); - listener = new GroupChangeListener(userViewer.getDisplay(), GroupMembersPart.this); - userAdminWrapper.addListener(listener); - } - - @Override - public void dispose() { - userAdminWrapper.removeListener(listener); - super.dispose(); - } - - @Override - public void refresh() { - userViewer.refresh(); - super.refresh(); - } - } - - /** - * Defines this table as being a potential target to add group membership - * (roles) to this group - */ - private class GroupDropListener extends ViewerDropAdapter { - private static final long serialVersionUID = 2893468717831451621L; - - private final UserAdminWrapper userAdminWrapper; - // private final LdifUsersTable myUserViewerCmp; - private final Group myGroup; - - public GroupDropListener(UserAdminWrapper userAdminWrapper, LdifUsersTable userTableViewerCmp, Group group) { - super(userTableViewerCmp.getTableViewer()); - this.userAdminWrapper = userAdminWrapper; - this.myGroup = group; - // this.myUserViewerCmp = userTableViewerCmp; - } - - @Override - public boolean validateDrop(Object target, int operation, TransferData transferType) { - // Target is always OK in a list only view - // TODO check if not a string - boolean validDrop = true; - return validDrop; - } - - @Override - public void drop(DropTargetEvent event) { - // TODO Is there an opportunity to perform the check before? - String newUserName = (String) event.data; - UserAdmin myUserAdmin = userAdminWrapper.getUserAdmin(); - Role role = myUserAdmin.getRole(newUserName); - if (role.getType() == Role.GROUP) { - Group newGroup = (Group) role; - Shell shell = getViewer().getControl().getShell(); - // Sanity checks - if (myGroup == newGroup) { // Equality - MessageDialog.openError(shell, "Forbidden addition ", "A group cannot be a member of itself."); - return; - } - - // Cycle - String myName = myGroup.getName(); - List myMemberships = getFlatGroups(myGroup); - if (myMemberships.contains(newGroup)) { - MessageDialog.openError(shell, "Forbidden addition: cycle", - "Cannot add " + newUserName + " to group " + myName + ". This would create a cycle"); - return; - } - - // Already member - List newGroupMemberships = getFlatGroups(newGroup); - if (newGroupMemberships.contains(myGroup)) { - MessageDialog.openError(shell, "Forbidden addition", - "Cannot add " + newUserName + " to group " + myName + ", this membership already exists"); - return; - } - userAdminWrapper.beginTransactionIfNeeded(); - myGroup.addMember(newGroup); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, myGroup)); - } else if (role.getType() == Role.USER) { - // TODO check if the group is already member of this group - WorkTransaction transaction = userAdminWrapper.beginTransactionIfNeeded(); - User user = (User) role; - myGroup.addMember(user); - if (UserAdminWrapper.COMMIT_ON_SAVE) - try { - transaction.commit(); - } catch (Exception e) { - throw new IllegalStateException( - "Cannot commit transaction " + "after user group membership update", e); - } - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, myGroup)); - } - super.drop(event); - } - - @Override - public boolean performDrop(Object data) { - // myUserViewerCmp.refresh(); - return true; - } - } - - // LOCAL HELPERS - // private Composite addSection(FormToolkit tk, Composite parent) { - // Section section = tk.createSection(parent, SWT.NO_FOCUS); - // section.setLayoutData(EclipseUiUtils.fillWidth()); - // Composite body = tk.createComposite(section, SWT.WRAP); - // body.setLayoutData(EclipseUiUtils.fillAll()); - // section.setClient(body); - // return body; - // } - - /** Creates label and text. */ - // private Text createLT(Composite parent, String label, String value) { - // FormToolkit toolkit = getManagedForm().getToolkit(); - // Label lbl = toolkit.createLabel(parent, label); - // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - // lbl.setFont(EclipseUiUtils.getBoldFont(parent)); - // Text text = toolkit.createText(parent, value, SWT.BORDER); - // text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT); - // return text; - // } - // - // Text createReadOnlyLT(Composite parent, String label, String value) { - // FormToolkit toolkit = getManagedForm().getToolkit(); - // Label lbl = toolkit.createLabel(parent, label); - // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - // lbl.setFont(EclipseUiUtils.getBoldFont(parent)); - // Text text = toolkit.createText(parent, value, SWT.NONE); - // text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - // text.setEditable(false); - // CmsUiUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT); - // return text; - // } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java deleted file mode 100644 index 73e4f5d11..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java +++ /dev/null @@ -1,251 +0,0 @@ -package org.argeo.cms.e4.users; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.inject.Inject; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.e4.users.providers.CommonNameLP; -import org.argeo.cms.e4.users.providers.DomainNameLP; -import org.argeo.cms.e4.users.providers.RoleIconLP; -import org.argeo.cms.e4.users.providers.UserDragListener; -import org.argeo.cms.swt.CmsException; -//import org.argeo.cms.ui.workbench.WorkbenchUiPlugin; -//import org.argeo.cms.ui.workbench.internal.useradmin.UiUserAdminListener; -//import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper; -//import org.argeo.cms.ui.workbench.internal.useradmin.providers.CommonNameLP; -//import org.argeo.cms.ui.workbench.internal.useradmin.providers.DomainNameLP; -//import org.argeo.cms.ui.workbench.internal.useradmin.providers.RoleIconLP; -//import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserDragListener; -//import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserTableDefaultDClickListener; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.util.naming.LdapAttrs; -import org.argeo.util.naming.LdapObjs; -import org.eclipse.e4.ui.di.Focus; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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.Display; -//import org.eclipse.ui.part.ViewPart; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdminEvent; -import org.osgi.service.useradmin.UserAdminListener; - -/** List all groups with filter */ -public class GroupsView { - private final static CmsLog log = CmsLog.getLog(GroupsView.class); - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".groupsView"; - - @Inject - private EPartService partService; - @Inject - private UserAdminWrapper userAdminWrapper; - - // UI Objects - private LdifUsersTable groupTableViewerCmp; - private TableViewer userViewer; - private List columnDefs = new ArrayList(); - - private UserAdminListener listener; - - @PostConstruct - public void createPartControl(Composite parent, ESelectionService selectionService) { - parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN); - - // Define the displayed columns - columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 19)); - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150)); - columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 100)); - // Only show technical DN to admin - // if (isAdmin) - // columnDefs.add(new ColumnDefinition(new UserNameLP(), - // "Distinguished Name", 300)); - - // Create and configure the table - groupTableViewerCmp = new MyUserTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - - groupTableViewerCmp.setColumnDefinitions(columnDefs); - // if (isAdmin) - // groupTableViewerCmp.populateWithStaticFilters(false, false); - // else - groupTableViewerCmp.populate(true, false); - - groupTableViewerCmp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - // Links - userViewer = groupTableViewerCmp.getTableViewer(); - userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService)); - // getViewSite().setSelectionProvider(userViewer); - userViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - selectionService.setSelection(selection.toList()); - } - }); - - // Really? - groupTableViewerCmp.refresh(); - - // Drag and drop - int operations = DND.DROP_COPY | DND.DROP_MOVE; - Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; - userViewer.addDragSupport(operations, tt, new UserDragListener(userViewer)); - - // // Register a useradmin listener - // listener = new UserAdminListener() { - // @Override - // public void roleChanged(UserAdminEvent event) { - // if (userViewer != null && !userViewer.getTable().isDisposed()) - // refresh(); - // } - // }; - // userAdminWrapper.addListener(listener); - // } - - // Register a useradmin listener - listener = new MyUiUAListener(parent.getDisplay()); - userAdminWrapper.addListener(listener); - } - - private class MyUiUAListener extends UiUserAdminListener { - public MyUiUAListener(Display display) { - super(display); - } - - @Override - public void roleChangedToUiThread(UserAdminEvent event) { - if (userViewer != null && !userViewer.getTable().isDisposed()) - refresh(); - } - } - - private class MyUserTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 8467999509931900367L; - - private boolean showSystemRoles = true; - - private final String[] knownProps = { LdapAttrs.uid.name(), LdapAttrs.cn.name(), LdapAttrs.DN }; - - public MyUserTableViewer(Composite parent, int style) { - super(parent, style); - showSystemRoles = CurrentUser.isInRole(CmsConstants.ROLE_ADMIN); - } - - protected void populateStaticFilters(Composite staticFilterCmp) { - staticFilterCmp.setLayout(new GridLayout()); - final Button showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK); - showSystemRoleBtn.setText("Show system roles"); - showSystemRoles = CurrentUser.isInRole(CmsConstants.ROLE_ADMIN); - showSystemRoleBtn.setSelection(showSystemRoles); - - showSystemRoleBtn.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -7033424592697691676L; - - @Override - public void widgetSelected(SelectionEvent e) { - showSystemRoles = showSystemRoleBtn.getSelection(); - refresh(); - } - - }); - } - - @Override - protected List listFilteredElements(String filter) { - Role[] roles; - try { - StringBuilder builder = new StringBuilder(); - StringBuilder tmpBuilder = new StringBuilder(); - if (EclipseUiUtils.notEmpty(filter)) - for (String prop : knownProps) { - tmpBuilder.append("("); - tmpBuilder.append(prop); - tmpBuilder.append("=*"); - tmpBuilder.append(filter); - tmpBuilder.append("*)"); - } - if (tmpBuilder.length() > 1) { - builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.groupOfNames.name()).append(")"); - // hide tokens - builder.append("(!(").append(LdapAttrs.DN).append("=*").append(CmsConstants.TOKENS_BASEDN) - .append("))"); - - if (!showSystemRoles) - builder.append("(!(").append(LdapAttrs.DN).append("=*").append(CmsConstants.SYSTEM_ROLES_BASEDN) - .append("))"); - builder.append("(|"); - builder.append(tmpBuilder.toString()); - builder.append("))"); - } else { - if (!showSystemRoles) - builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.groupOfNames.name()).append(")(!(").append(LdapAttrs.DN).append("=*") - .append(CmsConstants.SYSTEM_ROLES_BASEDN).append("))(!(").append(LdapAttrs.DN).append("=*") - .append(CmsConstants.TOKENS_BASEDN).append(")))"); - else - builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.groupOfNames.name()).append(")(!(").append(LdapAttrs.DN).append("=*") - .append(CmsConstants.TOKENS_BASEDN).append(")))"); - - } - roles = userAdminWrapper.getUserAdmin().getRoles(builder.toString()); - } catch (InvalidSyntaxException e) { - throw new CmsException("Unable to get roles with filter: " + filter, e); - } - List users = new ArrayList(); - for (Role role : roles) - if (!users.contains(role)) - users.add((User) role); - else - log.warn("Duplicated role: " + role); - - return users; - } - } - - public void refresh() { - groupTableViewerCmp.refresh(); - } - - @PreDestroy - public void dispose() { - userAdminWrapper.removeListener(listener); - } - - @Focus - public void setFocus() { - groupTableViewerCmp.setFocus(); - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/SecurityAdminImages.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/SecurityAdminImages.java deleted file mode 100644 index 7bbe3c727..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/SecurityAdminImages.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.cms.e4.users; - -import org.argeo.cms.ui.theme.CmsImages; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.swt.graphics.Image; - -/** Shared icons that must be declared programmatically . */ -public class SecurityAdminImages extends CmsImages { - private final static String PREFIX = "icons/"; - - public final static ImageDescriptor ICON_REMOVE_DESC = createDesc(PREFIX + "delete.png"); - public final static ImageDescriptor ICON_USER_DESC = createDesc(PREFIX + "person.png"); - - public final static Image ICON_USER = ICON_USER_DESC.createImage(); - public final static Image ICON_GROUP = createImg(PREFIX + "group.png"); - public final static Image ICON_WORKGROUP = createImg(PREFIX + "workgroup.png"); - public final static Image ICON_ROLE = createImg(PREFIX + "role.gif"); - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiAdminUtils.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiAdminUtils.java deleted file mode 100644 index fb48a47c3..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiAdminUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.argeo.cms.e4.users; - -import org.argeo.util.transaction.WorkTransaction; - -/** First effort to centralize back end methods used by the user admin UI */ -public class UiAdminUtils { - /* - * INTERNAL METHODS: Below methods are meant to stay here and are not part - * of a potential generic backend to manage the useradmin - */ - /** Easily notify the ActiveWindow that the transaction had a state change */ - public final static void notifyTransactionStateChange( - WorkTransaction userTransaction) { -// try { -// IWorkbenchWindow aww = PlatformUI.getWorkbench() -// .getActiveWorkbenchWindow(); -// ISourceProviderService sourceProviderService = (ISourceProviderService) aww -// .getService(ISourceProviderService.class); -// UserTransactionProvider esp = (UserTransactionProvider) sourceProviderService -// .getSourceProvider(UserTransactionProvider.TRANSACTION_STATE); -// esp.fireTransactionStateChange(); -// } catch (Exception e) { -// throw new CmsException("Unable to begin transaction", e); -// } - } - - /** - * Email addresses must match this regexp pattern ({@value #EMAIL_PATTERN}. - * Thanks to this tip. - */ - public final static String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiUserAdminListener.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiUserAdminListener.java deleted file mode 100644 index eb64aba0e..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UiUserAdminListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.argeo.cms.e4.users; - -import org.eclipse.swt.widgets.Display; -import org.osgi.service.useradmin.UserAdminEvent; -import org.osgi.service.useradmin.UserAdminListener; - -/** Convenience class to insure the call to refresh is done in the UI thread */ -public abstract class UiUserAdminListener implements UserAdminListener { - - private final Display display; - - public UiUserAdminListener(Display display) { - this.display = display; - } - - @Override - public void roleChanged(final UserAdminEvent event) { - display.asyncExec(new Runnable() { - @Override - public void run() { - roleChangedToUiThread(event); - } - }); - } - - public abstract void roleChangedToUiThread(UserAdminEvent event); -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java deleted file mode 100644 index dbb629c25..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.argeo.cms.e4.users; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.swt.CmsException; -import org.argeo.osgi.useradmin.UserDirectory; -import org.argeo.util.directory.DirectoryConf; -import org.argeo.util.transaction.WorkTransaction; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; -import org.osgi.service.useradmin.UserAdminListener; - -/** Centralise interaction with the UserAdmin in this bundle */ -public class UserAdminWrapper { - - private UserAdmin userAdmin; - // private ServiceReference userAdminServiceReference; -// private Set uris; - private Map> userDirectories = Collections - .synchronizedMap(new LinkedHashMap<>()); - private WorkTransaction userTransaction; - - // First effort to simplify UX while managing users and groups - public final static boolean COMMIT_ON_SAVE = true; - - // Registered listeners - List listeners = new ArrayList(); - - /** - * Starts a transaction if necessary. Should always been called together with - * {@link UserAdminWrapper#commitOrNotifyTransactionStateChange()} once the - * security model changes have been performed. - */ - public WorkTransaction beginTransactionIfNeeded() { - try { - // UserTransaction userTransaction = getUserTransaction(); - if (userTransaction.isNoTransactionStatus()) { - userTransaction.begin(); - // UiAdminUtils.notifyTransactionStateChange(userTransaction); - } - return userTransaction; - } catch (Exception e) { - throw new CmsException("Unable to begin transaction", e); - } - } - - /** - * Depending on the current application configuration, it will either commit the - * current transaction or throw a notification that the transaction state has - * changed (In the later case, it must be called from the UI thread). - */ - public void commitOrNotifyTransactionStateChange() { - try { - // UserTransaction userTransaction = getUserTransaction(); - if (userTransaction.isNoTransactionStatus()) - return; - - if (UserAdminWrapper.COMMIT_ON_SAVE) - userTransaction.commit(); - else - UiAdminUtils.notifyTransactionStateChange(userTransaction); - } catch (Exception e) { - throw new CmsException("Unable to clean transaction", e); - } - } - - // TODO implement safer mechanism - public void addListener(UserAdminListener userAdminListener) { - if (!listeners.contains(userAdminListener)) - listeners.add(userAdminListener); - } - - public void removeListener(UserAdminListener userAdminListener) { - if (listeners.contains(userAdminListener)) - listeners.remove(userAdminListener); - } - - public void notifyListeners(UserAdminEvent event) { - for (UserAdminListener listener : listeners) - listener.roleChanged(event); - } - - public Map getKnownBaseDns(boolean onlyWritable) { - Map dns = new HashMap(); - for (UserDirectory userDirectory : userDirectories.keySet()) { - Boolean readOnly = userDirectory.isReadOnly(); - String baseDn = userDirectory.getBase(); - - if (onlyWritable && readOnly) - continue; - if (baseDn.equalsIgnoreCase(CmsConstants.SYSTEM_ROLES_BASEDN)) - continue; - if (baseDn.equalsIgnoreCase(CmsConstants.TOKENS_BASEDN)) - continue; - dns.put(baseDn, DirectoryConf.propertiesAsUri(userDirectories.get(userDirectory)).toString()); - - } -// for (String uri : uris) { -// if (!uri.startsWith("/")) -// continue; -// Dictionary props = UserAdminConf.uriAsProperties(uri); -// String readOnly = UserAdminConf.readOnly.getValue(props); -// String baseDn = UserAdminConf.baseDn.getValue(props); -// -// if (onlyWritable && "true".equals(readOnly)) -// continue; -// if (baseDn.equalsIgnoreCase(NodeConstants.ROLES_BASEDN)) -// continue; -// if (baseDn.equalsIgnoreCase(NodeConstants.TOKENS_BASEDN)) -// continue; -// dns.put(baseDn, uri); -// } - return dns; - } - - public UserAdmin getUserAdmin() { - return userAdmin; - } - - public WorkTransaction getUserTransaction() { - return userTransaction; - } - - /* DEPENDENCY INJECTION */ - public void setUserAdmin(UserAdmin userAdmin, Map properties) { - this.userAdmin = userAdmin; -// this.uris = Collections.unmodifiableSortedSet(new TreeSet<>(properties.keySet())); - } - - public void setUserTransaction(WorkTransaction userTransaction) { - this.userTransaction = userTransaction; - } - - public void addUserDirectory(UserDirectory userDirectory, Map properties) { - userDirectories.put(userDirectory, new Hashtable<>(properties)); - } - - public void removeUserDirectory(UserDirectory userDirectory, Map properties) { - userDirectories.remove(userDirectory); - } - - // public void setUserAdminServiceReference( - // ServiceReference userAdminServiceReference) { - // this.userAdminServiceReference = userAdminServiceReference; - // } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java deleted file mode 100644 index 4fc59d30d..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java +++ /dev/null @@ -1,606 +0,0 @@ -package org.argeo.cms.e4.users; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.providers.CommonNameLP; -import org.argeo.cms.e4.users.providers.DomainNameLP; -import org.argeo.cms.e4.users.providers.MailLP; -import org.argeo.cms.e4.users.providers.UserNameLP; -import org.argeo.cms.swt.CmsException; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.util.naming.LdapAttrs; -import org.argeo.util.naming.LdapObjs; -import org.argeo.util.transaction.WorkTransaction; -import org.eclipse.jface.dialogs.IPageChangeProvider; -import org.eclipse.jface.dialogs.IPageChangedListener; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.dialogs.PageChangedEvent; -import org.eclipse.jface.wizard.IWizardContainer; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Wizard to update users */ -public class UserBatchUpdateWizard extends Wizard { - - private final static CmsLog log = CmsLog.getLog(UserBatchUpdateWizard.class); - private UserAdminWrapper userAdminWrapper; - - // pages - private ChooseCommandWizardPage chooseCommandPage; - private ChooseUsersWizardPage userListPage; - private ValidateAndLaunchWizardPage validatePage; - - // Various implemented commands keys - private final static String CMD_UPDATE_PASSWORD = "resetPassword"; - private final static String CMD_UPDATE_EMAIL = "resetEmail"; - private final static String CMD_GROUP_MEMBERSHIP = "groupMembership"; - - private final Map commands = new HashMap() { - private static final long serialVersionUID = 1L; - { - put("Reset password(s)", CMD_UPDATE_PASSWORD); - put("Reset email(s)", CMD_UPDATE_EMAIL); - // TODO implement role / group management - // put("Add/Remove from group", CMD_GROUP_MEMBERSHIP); - } - }; - - public UserBatchUpdateWizard(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } - - @Override - public void addPages() { - chooseCommandPage = new ChooseCommandWizardPage(); - addPage(chooseCommandPage); - userListPage = new ChooseUsersWizardPage(); - addPage(userListPage); - validatePage = new ValidateAndLaunchWizardPage(); - addPage(validatePage); - } - - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - WorkTransaction ut = userAdminWrapper.getUserTransaction(); - if (!ut.isNoTransactionStatus() && !MessageDialog.openConfirm(getShell(), "Existing Transaction", - "A user transaction is already existing, " + "are you sure you want to proceed ?")) - return false; - - // We cannot use jobs, user modifications are still meant to be done in - // the UIThread - // UpdateJob job = null; - // if (job != null) - // job.schedule(); - - if (CMD_UPDATE_PASSWORD.equals(chooseCommandPage.getCommand())) { - char[] newValue = chooseCommandPage.getPwdValue(); - if (newValue == null) - throw new CmsException("Password cannot be null or an empty string"); - ResetPassword job = new ResetPassword(userAdminWrapper, userListPage.getSelectedUsers(), newValue); - job.doUpdate(); - } else if (CMD_UPDATE_EMAIL.equals(chooseCommandPage.getCommand())) { - String newValue = chooseCommandPage.getEmailValue(); - if (newValue == null) - throw new CmsException("Password cannot be null or an empty string"); - ResetEmail job = new ResetEmail(userAdminWrapper, userListPage.getSelectedUsers(), newValue); - job.doUpdate(); - } - return true; - } - - public boolean canFinish() { - if (this.getContainer().getCurrentPage() == validatePage) - return true; - return false; - } - - private class ResetPassword { - private char[] newPwd; - private UserAdminWrapper userAdminWrapper; - private List usersToUpdate; - - public ResetPassword(UserAdminWrapper userAdminWrapper, List usersToUpdate, char[] newPwd) { - this.newPwd = newPwd; - this.usersToUpdate = usersToUpdate; - this.userAdminWrapper = userAdminWrapper; - } - - @SuppressWarnings("unchecked") - protected void doUpdate() { - userAdminWrapper.beginTransactionIfNeeded(); - try { - for (User user : usersToUpdate) { - // the char array is emptied after being used. - user.getCredentials().put(null, newPwd.clone()); - } - userAdminWrapper.commitOrNotifyTransactionStateChange(); - } catch (Exception e) { - throw new CmsException("Cannot perform batch update on users", e); - } finally { - WorkTransaction ut = userAdminWrapper.getUserTransaction(); - if (!ut.isNoTransactionStatus()) - ut.rollback(); - } - } - } - - private class ResetEmail { - private String newEmail; - private UserAdminWrapper userAdminWrapper; - private List usersToUpdate; - - public ResetEmail(UserAdminWrapper userAdminWrapper, List usersToUpdate, String newEmail) { - this.newEmail = newEmail; - this.usersToUpdate = usersToUpdate; - this.userAdminWrapper = userAdminWrapper; - } - - @SuppressWarnings("unchecked") - protected void doUpdate() { - userAdminWrapper.beginTransactionIfNeeded(); - try { - for (User user : usersToUpdate) { - // the char array is emptied after being used. - user.getProperties().put(LdapAttrs.mail.name(), newEmail); - } - - userAdminWrapper.commitOrNotifyTransactionStateChange(); - if (!usersToUpdate.isEmpty()) - userAdminWrapper.notifyListeners( - new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, usersToUpdate.get(0))); - } catch (Exception e) { - throw new CmsException("Cannot perform batch update on users", e); - } finally { - WorkTransaction ut = userAdminWrapper.getUserTransaction(); - if (!ut.isNoTransactionStatus()) - ut.rollback(); - } - } - } - - // @SuppressWarnings("unused") - // private class AddToGroup extends UpdateJob { - // private String groupID; - // private Session session; - // - // public AddToGroup(Session session, List nodesToUpdate, - // String groupID) { - // super(session, nodesToUpdate); - // this.session = session; - // this.groupID = groupID; - // } - // - // protected void doUpdate(Node node) { - // log.info("Add/Remove to group actions are not yet implemented"); - // // TODO implement this - // // try { - // // throw new CmsException("Not yet implemented"); - // // } catch (RepositoryException re) { - // // throw new CmsException( - // // "Unable to update boolean value for node " + node, re); - // // } - // } - // } - - // /** - // * Base privileged job that will be run asynchronously to perform the - // batch - // * update - // */ - // private abstract class UpdateJob extends PrivilegedJob { - // - // private final UserAdminWrapper userAdminWrapper; - // private final List usersToUpdate; - // - // protected abstract void doUpdate(User user); - // - // public UpdateJob(UserAdminWrapper userAdminWrapper, - // List usersToUpdate) { - // super("Perform update"); - // this.usersToUpdate = usersToUpdate; - // this.userAdminWrapper = userAdminWrapper; - // } - // - // @Override - // protected IStatus doRun(IProgressMonitor progressMonitor) { - // try { - // JcrMonitor monitor = new EclipseJcrMonitor(progressMonitor); - // int total = usersToUpdate.size(); - // monitor.beginTask("Performing change", total); - // userAdminWrapper.beginTransactionIfNeeded(); - // for (User user : usersToUpdate) { - // doUpdate(user); - // monitor.worked(1); - // } - // userAdminWrapper.getUserTransaction().commit(); - // } catch (Exception e) { - // throw new CmsException( - // "Cannot perform batch update on users", e); - // } finally { - // UserTransaction ut = userAdminWrapper.getUserTransaction(); - // try { - // if (ut.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION) - // ut.rollback(); - // } catch (IllegalStateException | SecurityException - // | SystemException e) { - // log.error("Unable to rollback session in 'finally', " - // + "the system might be in a dirty state"); - // e.printStackTrace(); - // } - // } - // return Status.OK_STATUS; - // } - // } - - // PAGES - /** - * Displays a combo box that enables user to choose which action to perform - */ - private class ChooseCommandWizardPage extends WizardPage { - private static final long serialVersionUID = -8069434295293996633L; - private Combo chooseCommandCmb; - private Button trueChk; - private Text valueTxt; - private Text pwdTxt; - private Text pwd2Txt; - - public ChooseCommandWizardPage() { - super("Choose a command to run."); - setTitle("Choose a command to run."); - } - - @Override - public void createControl(Composite parent) { - GridLayout gl = new GridLayout(); - Composite container = new Composite(parent, SWT.NO_FOCUS); - container.setLayout(gl); - - chooseCommandCmb = new Combo(container, SWT.READ_ONLY); - chooseCommandCmb.setLayoutData(EclipseUiUtils.fillWidth()); - String[] values = commands.keySet().toArray(new String[0]); - chooseCommandCmb.setItems(values); - - final Composite bottomPart = new Composite(container, SWT.NO_FOCUS); - bottomPart.setLayoutData(EclipseUiUtils.fillAll()); - bottomPart.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - chooseCommandCmb.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 1L; - - @Override - public void widgetSelected(SelectionEvent e) { - if (getCommand().equals(CMD_UPDATE_PASSWORD)) - populatePasswordCmp(bottomPart); - else if (getCommand().equals(CMD_UPDATE_EMAIL)) - populateEmailCmp(bottomPart); - else if (getCommand().equals(CMD_GROUP_MEMBERSHIP)) - populateGroupCmp(bottomPart); - else - populateBooleanFlagCmp(bottomPart); - checkPageComplete(); - bottomPart.layout(true, true); - } - }); - setControl(container); - } - - private void populateBooleanFlagCmp(Composite parent) { - EclipseUiUtils.clear(parent); - trueChk = new Button(parent, SWT.CHECK); - trueChk.setText("Do it. (It will to the contrary if unchecked)"); - trueChk.setSelection(true); - trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); - } - - private void populatePasswordCmp(Composite parent) { - EclipseUiUtils.clear(parent); - Composite body = new Composite(parent, SWT.NO_FOCUS); - - ModifyListener ml = new ModifyListener() { - private static final long serialVersionUID = -1558726363536729634L; - - @Override - public void modifyText(ModifyEvent event) { - checkPageComplete(); - } - }; - - body.setLayout(new GridLayout(2, false)); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - pwdTxt = EclipseUiUtils.createGridLP(body, "New password", ml); - pwd2Txt = EclipseUiUtils.createGridLP(body, "Repeat password", ml); - } - - private void populateEmailCmp(Composite parent) { - EclipseUiUtils.clear(parent); - Composite body = new Composite(parent, SWT.NO_FOCUS); - - ModifyListener ml = new ModifyListener() { - private static final long serialVersionUID = 2147704227294268317L; - - @Override - public void modifyText(ModifyEvent event) { - checkPageComplete(); - } - }; - - body.setLayout(new GridLayout(2, false)); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - valueTxt = EclipseUiUtils.createGridLT(body, "New e-mail", ml); - } - - private void checkPageComplete() { - String errorMsg = null; - if (chooseCommandCmb.getSelectionIndex() < 0) - errorMsg = "Please select an action"; - else if (CMD_UPDATE_EMAIL.equals(getCommand())) { - if (!valueTxt.getText().matches(UiAdminUtils.EMAIL_PATTERN)) - errorMsg = "Not a valid e-mail address"; - } else if (CMD_UPDATE_PASSWORD.equals(getCommand())) { - if (EclipseUiUtils.isEmpty(pwdTxt.getText()) || pwdTxt.getText().length() < 4) - errorMsg = "Please enter a password that is at least 4 character long"; - else if (!pwdTxt.getText().equals(pwd2Txt.getText())) - errorMsg = "Passwords are different"; - } - if (EclipseUiUtils.notEmpty(errorMsg)) { - setMessage(errorMsg, WizardPage.ERROR); - setPageComplete(false); - } else { - setMessage("Page complete, you can proceed to user choice", WizardPage.INFORMATION); - setPageComplete(true); - } - - getContainer().updateButtons(); - } - - private void populateGroupCmp(Composite parent) { - EclipseUiUtils.clear(parent); - trueChk = new Button(parent, SWT.CHECK); - trueChk.setText("Add to group. (It will remove user(s) from the " + "corresponding group if unchecked)"); - trueChk.setSelection(true); - trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); - } - - protected String getCommand() { - return commands.get(chooseCommandCmb.getItem(chooseCommandCmb.getSelectionIndex())); - } - - protected String getCommandLbl() { - return chooseCommandCmb.getItem(chooseCommandCmb.getSelectionIndex()); - } - - @SuppressWarnings("unused") - protected boolean getBoleanValue() { - // FIXME this is not consistent and will lead to errors. - if ("argeo:enabled".equals(getCommand())) - return trueChk.getSelection(); - else - return !trueChk.getSelection(); - } - - @SuppressWarnings("unused") - protected String getStringValue() { - String value = null; - if (valueTxt != null) { - value = valueTxt.getText(); - if ("".equals(value.trim())) - value = null; - } - return value; - } - - protected char[] getPwdValue() { - // We do not directly reset the password text fields: There is no - // need to over secure this process: setting a pwd to multi users - // at the same time is anyhow a bad practice and should be used only - // in test environment or for temporary access - if (pwdTxt == null || pwdTxt.isDisposed()) - return null; - else - return pwdTxt.getText().toCharArray(); - } - - protected String getEmailValue() { - // We do not directly reset the password text fields: There is no - // need to over secure this process: setting a pwd to multi users - // at the same time is anyhow a bad practice and should be used only - // in test environment or for temporary access - if (valueTxt == null || valueTxt.isDisposed()) - return null; - else - return valueTxt.getText(); - } - } - - /** - * Displays a list of users with a check box to be able to choose some of them - */ - private class ChooseUsersWizardPage extends WizardPage implements IPageChangedListener { - private static final long serialVersionUID = 7651807402211214274L; - private ChooseUserTableViewer userTableCmp; - - public ChooseUsersWizardPage() { - super("Choose Users"); - setTitle("Select users who will be impacted"); - } - - @Override - public void createControl(Composite parent) { - Composite pageCmp = new Composite(parent, SWT.NONE); - pageCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - // Define the displayed columns - List columnDefs = new ArrayList(); - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name", 150)); - columnDefs.add(new ColumnDefinition(new MailLP(), "E-mail", 150)); - columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 200)); - - // Only show technical DN to admin - if (CurrentUser.isInRole(CmsConstants.ROLE_ADMIN)) - columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name", 300)); - - userTableCmp = new ChooseUserTableViewer(pageCmp, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - userTableCmp.setLayoutData(EclipseUiUtils.fillAll()); - userTableCmp.setColumnDefinitions(columnDefs); - userTableCmp.populate(true, true); - userTableCmp.refresh(); - - setControl(pageCmp); - - // Add listener to update message when shown - final IWizardContainer wContainer = this.getContainer(); - if (wContainer instanceof IPageChangeProvider) { - ((IPageChangeProvider) wContainer).addPageChangedListener(this); - } - - } - - @Override - public void pageChanged(PageChangedEvent event) { - if (event.getSelectedPage() == this) { - String msg = "Chosen batch action: " + chooseCommandPage.getCommandLbl(); - ((WizardPage) event.getSelectedPage()).setMessage(msg); - } - } - - protected List getSelectedUsers() { - return userTableCmp.getSelectedUsers(); - } - - private class ChooseUserTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 5080437561015853124L; - private final String[] knownProps = { LdapAttrs.uid.name(), LdapAttrs.DN, LdapAttrs.cn.name(), - LdapAttrs.givenName.name(), LdapAttrs.sn.name(), LdapAttrs.mail.name() }; - - public ChooseUserTableViewer(Composite parent, int style) { - super(parent, style); - } - - @Override - protected List listFilteredElements(String filter) { - Role[] roles; - - try { - StringBuilder builder = new StringBuilder(); - - StringBuilder tmpBuilder = new StringBuilder(); - if (EclipseUiUtils.notEmpty(filter)) - for (String prop : knownProps) { - tmpBuilder.append("("); - tmpBuilder.append(prop); - tmpBuilder.append("=*"); - tmpBuilder.append(filter); - tmpBuilder.append("*)"); - } - if (tmpBuilder.length() > 1) { - builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.inetOrgPerson.name()).append(")(|"); - builder.append(tmpBuilder.toString()); - builder.append("))"); - } else - builder.append("(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.inetOrgPerson.name()).append(")"); - roles = userAdminWrapper.getUserAdmin().getRoles(builder.toString()); - } catch (InvalidSyntaxException e) { - throw new CmsException("Unable to get roles with filter: " + filter, e); - } - List users = new ArrayList(); - for (Role role : roles) - // Prevent current logged in user to perform batch on - // himself - if (!UserAdminUtils.isCurrentUser((User) role)) - users.add((User) role); - return users; - } - } - } - - /** Summary of input data before launching the process */ - private class ValidateAndLaunchWizardPage extends WizardPage implements IPageChangedListener { - private static final long serialVersionUID = 7098918351451743853L; - private ChosenUsersTableViewer userTableCmp; - - public ValidateAndLaunchWizardPage() { - super("Validate and launch"); - setTitle("Validate and launch"); - } - - @Override - public void createControl(Composite parent) { - Composite pageCmp = new Composite(parent, SWT.NO_FOCUS); - pageCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - List columnDefs = new ArrayList(); - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name", 150)); - columnDefs.add(new ColumnDefinition(new MailLP(), "E-mail", 150)); - columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 200)); - // Only show technical DN to admin - if (CurrentUser.isInRole(CmsConstants.ROLE_ADMIN)) - columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name", 300)); - userTableCmp = new ChosenUsersTableViewer(pageCmp, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - userTableCmp.setLayoutData(EclipseUiUtils.fillAll()); - userTableCmp.setColumnDefinitions(columnDefs); - userTableCmp.populate(false, false); - userTableCmp.refresh(); - setControl(pageCmp); - // Add listener to update message when shown - final IWizardContainer wContainer = this.getContainer(); - if (wContainer instanceof IPageChangeProvider) { - ((IPageChangeProvider) wContainer).addPageChangedListener(this); - } - } - - @Override - public void pageChanged(PageChangedEvent event) { - if (event.getSelectedPage() == this) { - @SuppressWarnings({ "unchecked", "rawtypes" }) - Object[] values = ((ArrayList) userListPage.getSelectedUsers()) - .toArray(new Object[userListPage.getSelectedUsers().size()]); - userTableCmp.getTableViewer().setInput(values); - String msg = "Following batch action: [" + chooseCommandPage.getCommandLbl() - + "] will be perfomed on the users listed below.\n"; - // + "Are you sure you want to proceed?"; - setMessage(msg); - } - } - - private class ChosenUsersTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 7814764735794270541L; - - public ChosenUsersTableViewer(Composite parent, int style) { - super(parent, style); - } - - @Override - protected List listFilteredElements(String filter) { - return userListPage.getSelectedUsers(); - } - } - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserEditor.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserEditor.java deleted file mode 100644 index 66f442082..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserEditor.java +++ /dev/null @@ -1,535 +0,0 @@ -package org.argeo.cms.e4.users; - -import static org.argeo.cms.auth.UserAdminUtils.getProperty; -import static org.argeo.util.naming.LdapAttrs.cn; -import static org.argeo.util.naming.LdapAttrs.givenName; -import static org.argeo.util.naming.LdapAttrs.mail; -import static org.argeo.util.naming.LdapAttrs.sn; -import static org.argeo.util.naming.LdapAttrs.uid; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.inject.Inject; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.providers.CommonNameLP; -import org.argeo.cms.e4.users.providers.DomainNameLP; -import org.argeo.cms.e4.users.providers.RoleIconLP; -import org.argeo.cms.e4.users.providers.UserFilter; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.ui.eclipse.forms.AbstractFormPart; -//import org.argeo.cms.ui.eclipse.forms.FormToolkit; -import org.argeo.cms.ui.eclipse.forms.IManagedForm; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.dialogs.TrayDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerDropAdapter; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.dnd.TransferData; -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.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.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Display/edit the properties of a given user */ -public class UserEditor extends AbstractRoleEditor { - // final static String ID = "UserEditor.mainPage"; - - @Inject - private EPartService partService; - - // private final UserEditor editor; - // private UserAdminWrapper userAdminWrapper; - - // Local configuration - // private final int PRE_TITLE_INDENT = 10; - - // public UserMainPage(FormEditor editor, UserAdminWrapper userAdminWrapper) { - // super(editor, ID, "Main"); - // this.editor = (UserEditor) editor; - // this.userAdminWrapper = userAdminWrapper; - // } - - // protected void createFormContent(final IManagedForm mf) { - // ScrolledForm form = mf.getForm(); - // Composite body = form.getBody(); - // GridLayout mainLayout = new GridLayout(); - // // mainLayout.marginRight = 10; - // body.setLayout(mainLayout); - // User user = editor.getDisplayedUser(); - // appendOverviewPart(body, user); - // // Remove to ability to force the password for his own user. The user - // // must then use the change pwd feature - // appendMemberOfPart(body, user); - // } - - @Override - protected void createUi(Composite body) { - // Composite body = new Composite(parent, SWT.BORDER); - GridLayout mainLayout = new GridLayout(); - // mainLayout.marginRight = 10; - body.setLayout(mainLayout); - // body.getParent().setLayout(new GridLayout()); - // body.setLayoutData(CmsUiUtils.fillAll()); - User user = getDisplayedUser(); - appendOverviewPart(body, user); - // Remove to ability to force the password for his own user. The user - // must then use the change pwd feature - appendMemberOfPart(body, user); - } - - /** Creates the general section */ - private void appendOverviewPart(final Composite parent, final User user) { - // FormToolkit tk = getManagedForm().getToolkit(); - - // Section section = tk.createSection(parent, SWT.NO_FOCUS); - // GridData gd = EclipseUiUtils.fillWidth(); - // // gd.verticalAlignment = PRE_TITLE_INDENT; - // section.setLayoutData(gd); - Composite body = new Composite(parent, SWT.NONE); - body.setLayoutData(EclipseUiUtils.fillWidth()); - // section.setClient(body); - // body.setLayout(new GridLayout(6, false)); - body.setLayout(new GridLayout(2, false)); - - Text commonName = createReadOnlyLT(body, "Name", getProperty(user, cn)); - Text distinguishedName = createReadOnlyLT(body, "Login", getProperty(user, uid)); - Text firstName = createLT(body, "First name", getProperty(user, givenName)); - Text lastName = createLT(body, "Last name", getProperty(user, sn)); - Text email = createLT(body, "Email", getProperty(user, mail)); - - Link resetPwdLk = new Link(body, SWT.NONE); - if (!UserAdminUtils.isCurrentUser(user)) { - resetPwdLk.setText("Reset password"); - } - resetPwdLk.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); - - // create form part (controller) - AbstractFormPart part = new AbstractFormPart() { - private MainInfoListener listener; - - @Override - public void initialize(IManagedForm form) { - super.initialize(form); - listener = new MainInfoListener(parent.getDisplay(), this); - userAdminWrapper.addListener(listener); - } - - @Override - public void dispose() { - userAdminWrapper.removeListener(listener); - super.dispose(); - } - - @SuppressWarnings("unchecked") - public void commit(boolean onSave) { - // TODO Sanity checks (mail validity...) - user.getProperties().put(LdapAttrs.givenName.name(), firstName.getText()); - user.getProperties().put(LdapAttrs.sn.name(), lastName.getText()); - user.getProperties().put(LdapAttrs.cn.name(), commonName.getText()); - user.getProperties().put(LdapAttrs.mail.name(), email.getText()); - super.commit(onSave); - } - - @Override - public void refresh() { - distinguishedName.setText(UserAdminUtils.getProperty(user, LdapAttrs.uid.name())); - commonName.setText(UserAdminUtils.getProperty(user, LdapAttrs.cn.name())); - firstName.setText(UserAdminUtils.getProperty(user, LdapAttrs.givenName.name())); - lastName.setText(UserAdminUtils.getProperty(user, LdapAttrs.sn.name())); - email.setText(UserAdminUtils.getProperty(user, LdapAttrs.mail.name())); - refreshFormTitle(user); - super.refresh(); - } - }; - - // Improve this: automatically generate CN when first or last name - // changes - ModifyListener cnML = new ModifyListener() { - private static final long serialVersionUID = 4298649222869835486L; - - @Override - public void modifyText(ModifyEvent event) { - String first = firstName.getText(); - String last = lastName.getText(); - String cn = first.trim() + " " + last.trim() + " "; - cn = cn.trim(); - commonName.setText(cn); - // getManagedForm().getForm().setText(cn); - updateEditorTitle(cn); - } - }; - firstName.addModifyListener(cnML); - lastName.addModifyListener(cnML); - - ModifyListener defaultListener = new FormPartML(part); - firstName.addModifyListener(defaultListener); - lastName.addModifyListener(defaultListener); - email.addModifyListener(defaultListener); - - if (!UserAdminUtils.isCurrentUser(user)) - resetPwdLk.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 5881800534589073787L; - - @Override - public void widgetSelected(SelectionEvent e) { - new ChangePasswordDialog(user, "Reset password").open(); - } - }); - - getManagedForm().addPart(part); - } - - private class ChangePasswordDialog extends TrayDialog { - private static final long serialVersionUID = 2843538207460082349L; - - private User user; - private Text password1; - private Text password2; - private String title; - // private FormToolkit tk; - - public ChangePasswordDialog(User user, String title) { - super(Display.getDefault().getActiveShell()); - // this.tk = tk; - this.user = user; - this.title = title; - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - Composite body = new Composite(dialogarea, SWT.NO_FOCUS); - body.setLayoutData(EclipseUiUtils.fillAll()); - GridLayout layout = new GridLayout(2, false); - body.setLayout(layout); - - password1 = createLP(body, "New password", ""); - password2 = createLP(body, "Repeat password", ""); - parent.pack(); - return body; - } - - @SuppressWarnings("unchecked") - @Override - protected void okPressed() { - String msg = null; - - if (password1.getText().equals("")) - msg = "Password cannot be empty"; - else if (password1.getText().equals(password2.getText())) { - char[] newPassword = password1.getText().toCharArray(); - // userAdminWrapper.beginTransactionIfNeeded(); - userAdminWrapper.beginTransactionIfNeeded(); - user.getCredentials().put(null, newPassword); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - super.okPressed(); - } else { - msg = "Passwords are not equals"; - } - - if (EclipseUiUtils.notEmpty(msg)) - MessageDialog.openError(getParentShell(), "Cannot reset pasword", msg); - } - - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText(title); - } - } - - private LdifUsersTable appendMemberOfPart(final Composite parent, User user) { - // Section section = addSection(tk, parent, "Roles"); - // Composite body = (Composite) section.getClient(); - // Composite body= parent; - Composite body = new Composite(parent, SWT.BORDER); - body.setLayout(new GridLayout()); - body.setLayoutData(CmsSwtUtils.fillAll()); - - // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN); - - // Displayed columns - List columnDefs = new ArrayList(); - columnDefs.add(new ColumnDefinition(new RoleIconLP(), "", 0, 24)); - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Name", 150)); - columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 100)); - // Only show technical DN to administrators - // if (isAdmin) - // columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name", - // 300)); - - // Create and configure the table - final LdifUsersTable userViewerCmp = new MyUserTableViewer(body, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, user); - - userViewerCmp.setColumnDefinitions(columnDefs); - // if (isAdmin) - // userViewerCmp.populateWithStaticFilters(false, false); - // else - userViewerCmp.populate(true, false); - GridData gd = EclipseUiUtils.fillAll(); - gd.heightHint = 500; - userViewerCmp.setLayoutData(gd); - - // Controllers - TableViewer userViewer = userViewerCmp.getTableViewer(); - userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService)); - int operations = DND.DROP_COPY | DND.DROP_MOVE; - Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; - GroupDropListener dropL = new GroupDropListener(userAdminWrapper, userViewer, user); - userViewer.addDropSupport(operations, tt, dropL); - - AbstractFormPart part = new AbstractFormPart() { - - private GroupChangeListener listener; - - @Override - public void initialize(IManagedForm form) { - super.initialize(form); - listener = new GroupChangeListener(parent.getDisplay(), this); - userAdminWrapper.addListener(listener); - } - - public void commit(boolean onSave) { - super.commit(onSave); - } - - @Override - public void dispose() { - userAdminWrapper.removeListener(listener); - super.dispose(); - } - - @Override - public void refresh() { - userViewerCmp.refresh(); - super.refresh(); - } - }; - getManagedForm().addPart(part); - // addRemoveAbitily(body, userViewer, user); - // userViewerCmp.refresh(); - String tooltip = "Remove " + UserAdminUtils.getUserLocalId(user.getName()) + " from the below selected groups"; - Action action = new RemoveMembershipAction(userViewer, user, tooltip, SecurityAdminImages.ICON_REMOVE_DESC); - ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); - ToolBar toolBar = toolBarManager.createControl(body); - toolBar.setLayoutData(CmsSwtUtils.fillWidth()); - toolBarManager.add(action); - toolBarManager.update(true); - return userViewerCmp; - } - - private class MyUserTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 2653790051461237329L; - - private Button showSystemRoleBtn; - - private final User user; - private final UserFilter userFilter; - - public MyUserTableViewer(Composite parent, int style, User user) { - super(parent, style, true); - this.user = user; - userFilter = new UserFilter(); - } - - protected void populateStaticFilters(Composite staticFilterCmp) { - staticFilterCmp.setLayout(new GridLayout()); - showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK); - showSystemRoleBtn.setText("Show system roles"); - boolean showSysRole = CurrentUser.isInRole(CmsConstants.ROLE_ADMIN); - showSystemRoleBtn.setSelection(showSysRole); - userFilter.setShowSystemRole(showSysRole); - showSystemRoleBtn.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = -7033424592697691676L; - - @Override - public void widgetSelected(SelectionEvent e) { - userFilter.setShowSystemRole(showSystemRoleBtn.getSelection()); - refresh(); - } - }); - } - - @Override - protected List listFilteredElements(String filter) { - List users = (List) getFlatGroups(null); - List filteredUsers = new ArrayList(); - if (users.contains(user)) - users.remove(user); - userFilter.setSearchText(filter); - for (User user : users) - if (userFilter.select(null, null, user)) - filteredUsers.add(user); - return filteredUsers; - } - } - - // private void addRemoveAbility(Composite parent, TableViewer userViewer, User - // user) { - // // Section section = sectionPart.getSection(); - // ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); - // ToolBar toolbar = toolBarManager.createControl(parent); - // final Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND); - // toolbar.setCursor(handCursor); - // toolbar.addDisposeListener(new DisposeListener() { - // private static final long serialVersionUID = 3882131405820522925L; - // - // public void widgetDisposed(DisposeEvent e) { - // if ((handCursor != null) && (handCursor.isDisposed() == false)) { - // handCursor.dispose(); - // } - // } - // }); - // - // String tooltip = "Remove " + UserAdminUtils.getUserLocalId(user.getName()) + - // " from the below selected groups"; - // Action action = new RemoveMembershipAction(userViewer, user, tooltip, - // SecurityAdminImages.ICON_REMOVE_DESC); - // toolBarManager.add(action); - // toolBarManager.update(true); - // // section.setTextClient(toolbar); - // } - - private class RemoveMembershipAction extends Action { - private static final long serialVersionUID = -1337713097184522588L; - - private final TableViewer userViewer; - private final User user; - - RemoveMembershipAction(TableViewer userViewer, User user, String name, ImageDescriptor img) { - super(name, img); - this.userViewer = userViewer; - this.user = user; - } - - @Override - public void run() { - ISelection selection = userViewer.getSelection(); - if (selection.isEmpty()) - return; - - @SuppressWarnings("unchecked") - Iterator it = ((IStructuredSelection) selection).iterator(); - List groups = new ArrayList(); - while (it.hasNext()) { - Group currGroup = it.next(); - groups.add(currGroup); - } - - userAdminWrapper.beginTransactionIfNeeded(); - for (Group group : groups) { - group.removeMember(user); - } - userAdminWrapper.commitOrNotifyTransactionStateChange(); - for (Group group : groups) { - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group)); - } - } - } - - /** - * Defines the table as being a potential target to add group memberships - * (roles) to this user - */ - private class GroupDropListener extends ViewerDropAdapter { - private static final long serialVersionUID = 2893468717831451621L; - - private final UserAdminWrapper myUserAdminWrapper; - private final User myUser; - - public GroupDropListener(UserAdminWrapper userAdminWrapper, Viewer userViewer, User user) { - super(userViewer); - this.myUserAdminWrapper = userAdminWrapper; - this.myUser = user; - } - - @Override - public boolean validateDrop(Object target, int operation, TransferData transferType) { - // Target is always OK in a list only view - // TODO check if not a string - boolean validDrop = true; - return validDrop; - } - - @Override - public void drop(DropTargetEvent event) { - String name = (String) event.data; - UserAdmin myUserAdmin = myUserAdminWrapper.getUserAdmin(); - Role role = myUserAdmin.getRole(name); - // TODO this check should be done before. - if (role.getType() == Role.GROUP) { - // TODO check if the user is already member of this group - - myUserAdminWrapper.beginTransactionIfNeeded(); - Group group = (Group) role; - group.addMember(myUser); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - myUserAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group)); - } - super.drop(event); - } - - @Override - public boolean performDrop(Object data) { - // userTableViewerCmp.refresh(); - return true; - } - } - - // LOCAL HELPERS - private void refreshFormTitle(User group) { - // getManagedForm().getForm().setText(UserAdminUtils.getProperty(group, - // LdapAttrs.cn.name())); - } - - /** Appends a section with a title */ - // private Section addSection(FormToolkit tk, Composite parent, String title) { - // Section section = tk.createSection(parent, Section.TITLE_BAR); - // GridData gd = EclipseUiUtils.fillWidth(); - // gd.verticalAlignment = PRE_TITLE_INDENT; - // section.setLayoutData(gd); - // section.setText(title); - // // section.getMenu().setVisible(true); - // - // Composite body = tk.createComposite(section, SWT.WRAP); - // body.setLayoutData(EclipseUiUtils.fillAll()); - // section.setClient(body); - // - // return section; - // } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserTableDefaultDClickListener.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserTableDefaultDClickListener.java deleted file mode 100644 index c6d024ebc..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserTableDefaultDClickListener.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.argeo.cms.e4.users; - -import org.argeo.cms.e4.CmsE4Utils; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.User; - -/** - * Default double click listener for the various user tables, will open the - * clicked item in the editor - */ -public class UserTableDefaultDClickListener implements IDoubleClickListener { - private final EPartService partService; - - public UserTableDefaultDClickListener(EPartService partService) { - this.partService = partService; - } - - public void doubleClick(DoubleClickEvent evt) { - if (evt.getSelection().isEmpty()) - return; - Object obj = ((IStructuredSelection) evt.getSelection()).getFirstElement(); - User user = (User) obj; - - String editorId = getEditorId(user); - CmsE4Utils.openEditor(partService, editorId, LdapAttrs.uid.name(), user.getName()); - } - - protected String getEditorId(User user) { - if (user instanceof Group) - return "org.argeo.cms.e4.partdescriptor.groupEditor"; - else - return "org.argeo.cms.e4.partdescriptor.userEditor"; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java deleted file mode 100644 index 720945c4c..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java +++ /dev/null @@ -1,182 +0,0 @@ -package org.argeo.cms.e4.users; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.inject.Inject; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.e4.users.providers.CommonNameLP; -import org.argeo.cms.e4.users.providers.DomainNameLP; -import org.argeo.cms.e4.users.providers.MailLP; -import org.argeo.cms.e4.users.providers.UserDragListener; -import org.argeo.cms.e4.users.providers.UserNameLP; -import org.argeo.cms.swt.CmsException; -import org.argeo.eclipse.ui.ColumnDefinition; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.parts.LdifUsersTable; -import org.argeo.util.naming.LdapAttrs; -import org.argeo.util.naming.LdapObjs; -import org.eclipse.e4.ui.di.Focus; -import org.eclipse.e4.ui.workbench.modeling.EPartService; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdminEvent; -import org.osgi.service.useradmin.UserAdminListener; - -/** List all users with filter - based on Ldif userAdmin */ -public class UsersView { - // private final static Log log = LogFactory.getLog(UsersView.class); - - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".usersView"; - - @Inject - private UserAdminWrapper userAdminWrapper; - @Inject - private EPartService partService; - - // UI Objects - private LdifUsersTable userTableViewerCmp; - private TableViewer userViewer; - private List columnDefs = new ArrayList(); - - private UserAdminListener listener; - - @PostConstruct - public void createPartControl(Composite parent, ESelectionService selectionService) { - - parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); - // Define the displayed columns - columnDefs.add(new ColumnDefinition(new CommonNameLP(), "Common Name", 150)); - columnDefs.add(new ColumnDefinition(new MailLP(), "E-mail", 150)); - columnDefs.add(new ColumnDefinition(new DomainNameLP(), "Domain", 200)); - // Only show technical DN to admin - if (CurrentUser.isInRole(CmsConstants.ROLE_ADMIN)) - columnDefs.add(new ColumnDefinition(new UserNameLP(), "Distinguished Name", 300)); - - // Create and configure the table - userTableViewerCmp = new MyUserTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - userTableViewerCmp.setLayoutData(EclipseUiUtils.fillAll()); - userTableViewerCmp.setColumnDefinitions(columnDefs); - userTableViewerCmp.populate(true, false); - - // Links - userViewer = userTableViewerCmp.getTableViewer(); - userViewer.addDoubleClickListener(new UserTableDefaultDClickListener(partService)); - userViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - selectionService.setSelection(selection.toList()); - } - }); - // getViewSite().setSelectionProvider(userViewer); - - // Really? - userTableViewerCmp.refresh(); - - // Drag and drop - int operations = DND.DROP_COPY | DND.DROP_MOVE; - Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; - userViewer.addDragSupport(operations, tt, new UserDragListener(userViewer)); - - // Register a useradmin listener - listener = new MyUiUAListener(parent.getDisplay()); - userAdminWrapper.addListener(listener); - } - - private class MyUiUAListener extends UiUserAdminListener { - public MyUiUAListener(Display display) { - super(display); - } - - @Override - public void roleChangedToUiThread(UserAdminEvent event) { - if (userViewer != null && !userViewer.getTable().isDisposed()) - refresh(); - } - } - - private class MyUserTableViewer extends LdifUsersTable { - private static final long serialVersionUID = 8467999509931900367L; - - private final String[] knownProps = { LdapAttrs.DN, LdapAttrs.uid.name(), LdapAttrs.cn.name(), - LdapAttrs.givenName.name(), LdapAttrs.sn.name(), LdapAttrs.mail.name() }; - - public MyUserTableViewer(Composite parent, int style) { - super(parent, style); - } - - @Override - protected List listFilteredElements(String filter) { - Role[] roles; - - try { - StringBuilder builder = new StringBuilder(); - - StringBuilder tmpBuilder = new StringBuilder(); - if (EclipseUiUtils.notEmpty(filter)) - for (String prop : knownProps) { - tmpBuilder.append("("); - tmpBuilder.append(prop); - tmpBuilder.append("=*"); - tmpBuilder.append(filter); - tmpBuilder.append("*)"); - } - if (tmpBuilder.length() > 1) { - builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.inetOrgPerson.name()).append(")(|"); - builder.append(tmpBuilder.toString()); - builder.append("))"); - } else - builder.append("(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.inetOrgPerson.name()).append(")"); - roles = userAdminWrapper.getUserAdmin().getRoles(builder.toString()); - } catch (InvalidSyntaxException e) { - throw new CmsException("Unable to get roles with filter: " + filter, e); - } - List users = new ArrayList(); - for (Role role : roles) - // if (role.getType() == Role.USER && role.getType() != - // Role.GROUP) - users.add((User) role); - return users; - } - } - - public void refresh() { - userTableViewerCmp.refresh(); - } - - // Override generic view methods - @PreDestroy - public void dispose() { - userAdminWrapper.removeListener(listener); - } - - @Focus - public void setFocus() { - userTableViewerCmp.setFocus(); - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteGroups.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteGroups.java deleted file mode 100644 index 742bc3f5f..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteGroups.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.argeo.cms.e4.users.handlers; - -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Named; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.GroupsView; -import org.argeo.cms.e4.users.UserAdminWrapper; -import org.eclipse.e4.core.di.annotations.CanExecute; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Delete the selected groups */ -public class DeleteGroups { - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + - // ".deleteGroups"; - - /* DEPENDENCY INJECTION */ - @Inject - private UserAdminWrapper userAdminWrapper; - - @Inject - ESelectionService selectionService; - - @SuppressWarnings("unchecked") - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - // ISelection selection = null;// HandlerUtil.getCurrentSelection(event); - // if (selection.isEmpty()) - // return null; - // - // List groups = new ArrayList(); - // Iterator it = ((IStructuredSelection) selection).iterator(); - - List selection = (List) selectionService.getSelection(); - if (selection == null) - return; - - StringBuilder builder = new StringBuilder(); - for (Group group : selection) { - Group currGroup = group; - String groupName = UserAdminUtils.getUserLocalId(currGroup.getName()); - // TODO add checks - builder.append(groupName).append("; "); - // groups.add(currGroup); - } - - if (!MessageDialog.openQuestion(Display.getCurrent().getActiveShell(), "Delete Groups", "Are you sure that you " - + "want to delete these groups?\n" + builder.substring(0, builder.length() - 2))) - return; - - userAdminWrapper.beginTransactionIfNeeded(); - UserAdmin userAdmin = userAdminWrapper.getUserAdmin(); - // IWorkbenchPage iwp = - // HandlerUtil.getActiveWorkbenchWindow(event).getActivePage(); - for (Group group : selection) { - String groupName = group.getName(); - // TODO find a way to close the editor cleanly if opened. Cannot be - // done through the UserAdminListeners, it causes a - // java.util.ConcurrentModificationException because disposing the - // editor unregisters and disposes the listener - // IEditorPart part = iwp.findEditor(new UserEditorInput(groupName)); - // if (part != null) - // iwp.closeEditor(part, false); - userAdmin.removeRole(groupName); - } - userAdminWrapper.commitOrNotifyTransactionStateChange(); - - // Update the view - for (Group group : selection) { - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, group)); - } - - // return null; - } - - @CanExecute - public boolean canExecute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - return part.getObject() instanceof GroupsView && selectionService.getSelection() != null; - } - - /* DEPENDENCY INJECTION */ - // public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - // this.userAdminWrapper = userAdminWrapper; - // } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteUsers.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteUsers.java deleted file mode 100644 index d1afd2210..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/DeleteUsers.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.argeo.cms.e4.users.handlers; - -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Named; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.UserAdminWrapper; -import org.argeo.cms.e4.users.UsersView; -import org.eclipse.e4.core.di.annotations.CanExecute; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.services.IServiceConstants; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Delete the selected users */ -public class DeleteUsers { - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".deleteUsers"; - - /* DEPENDENCY INJECTION */ - @Inject - private UserAdminWrapper userAdminWrapper; - - @SuppressWarnings("unchecked") - @Execute - public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - // ISelection selection = null;// HandlerUtil.getCurrentSelection(event); - // if (selection.isEmpty()) - // return null; - List selection = (List) selectionService.getSelection(); - if (selection == null) - return; - -// Iterator it = ((IStructuredSelection) selection).iterator(); -// List users = new ArrayList(); - StringBuilder builder = new StringBuilder(); - - for(User user:selection) { - User currUser = user; -// User currUser = it.next(); - String userName = UserAdminUtils.getUserLocalId(currUser.getName()); - if (UserAdminUtils.isCurrentUser(currUser)) { - MessageDialog.openError(Display.getCurrent().getActiveShell(), "Deletion forbidden", - "You cannot delete your own user this way."); - return; - } - builder.append(userName).append("; "); -// users.add(currUser); - } - - if (!MessageDialog.openQuestion(Display.getCurrent().getActiveShell(), "Delete Users", - "Are you sure that you want to delete these users?\n" + builder.substring(0, builder.length() - 2))) - return; - - userAdminWrapper.beginTransactionIfNeeded(); - UserAdmin userAdmin = userAdminWrapper.getUserAdmin(); - // IWorkbenchPage iwp = - // HandlerUtil.getActiveWorkbenchWindow(event).getActivePage(); - - for (User user : selection) { - String userName = user.getName(); - // TODO find a way to close the editor cleanly if opened. Cannot be - // done through the UserAdminListeners, it causes a - // java.util.ConcurrentModificationException because disposing the - // editor unregisters and disposes the listener - // IEditorPart part = iwp.findEditor(new UserEditorInput(userName)); - // if (part != null) - // iwp.closeEditor(part, false); - userAdmin.removeRole(userName); - } - userAdminWrapper.commitOrNotifyTransactionStateChange(); - - for (User user : selection) { - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, user)); - } - } - - @CanExecute - public boolean canExecute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { - return part.getObject() instanceof UsersView && selectionService.getSelection() != null; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java deleted file mode 100644 index 41e14e097..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.argeo.cms.e4.users.handlers; - -import java.util.Dictionary; -import java.util.Map; - -import javax.inject.Inject; - -import org.argeo.cms.e4.users.UserAdminWrapper; -import org.argeo.cms.swt.CmsException; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.util.directory.DirectoryConf; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Create a new group */ -public class NewGroup { - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".newGroup"; - - /* DEPENDENCY INJECTION */ - @Inject - private UserAdminWrapper userAdminWrapper; - - @Execute - public Object execute() { - NewGroupWizard newGroupWizard = new NewGroupWizard(); - newGroupWizard.setWindowTitle("Group creation"); - WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), newGroupWizard); - dialog.open(); - return null; - } - - private class NewGroupWizard extends Wizard { - - // Pages - private MainGroupInfoWizardPage mainGroupInfo; - - // UI fields - private Text dNameTxt, commonNameTxt, descriptionTxt; - private Combo baseDnCmb; - - public NewGroupWizard() { - } - - @Override - public void addPages() { - mainGroupInfo = new MainGroupInfoWizardPage(); - addPage(mainGroupInfo); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - String commonName = commonNameTxt.getText(); - try { - userAdminWrapper.beginTransactionIfNeeded(); - String dn = getDn(commonName); - Group group = (Group) userAdminWrapper.getUserAdmin().createRole(dn, Role.GROUP); - Dictionary props = group.getProperties(); - String descStr = descriptionTxt.getText(); - if (EclipseUiUtils.notEmpty(descStr)) - props.put(LdapAttrs.description.name(), descStr); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CREATED, group)); - return true; - } catch (Exception e) { - ErrorFeedback.show("Cannot create new group " + commonName, e); - return false; - } - } - - private class MainGroupInfoWizardPage extends WizardPage implements FocusListener { - private static final long serialVersionUID = -3150193365151601807L; - - public MainGroupInfoWizardPage() { - super("Main"); - setTitle("General information"); - setMessage("Please choose a domain, provide a common name " + "and a free description"); - } - - @Override - public void createControl(Composite parent) { - Composite bodyCmp = new Composite(parent, SWT.NONE); - setControl(bodyCmp); - bodyCmp.setLayout(new GridLayout(2, false)); - - dNameTxt = EclipseUiUtils.createGridLT(bodyCmp, "Distinguished name"); - dNameTxt.setEnabled(false); - - baseDnCmb = createGridLC(bodyCmp, "Base DN"); - // Initialise before adding the listener to avoid NPE - initialiseDnCmb(baseDnCmb); - baseDnCmb.addFocusListener(this); - - commonNameTxt = EclipseUiUtils.createGridLT(bodyCmp, "Common name"); - commonNameTxt.addFocusListener(this); - - Label descLbl = new Label(bodyCmp, SWT.LEAD); - descLbl.setText("Description"); - descLbl.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false)); - descriptionTxt = new Text(bodyCmp, SWT.LEAD | SWT.MULTI | SWT.WRAP | SWT.BORDER); - descriptionTxt.setLayoutData(EclipseUiUtils.fillAll()); - descriptionTxt.addFocusListener(this); - - // Initialize buttons - setPageComplete(false); - getContainer().updateButtons(); - } - - @Override - public void focusLost(FocusEvent event) { - String name = commonNameTxt.getText(); - if (EclipseUiUtils.isEmpty(name)) - dNameTxt.setText(""); - else - dNameTxt.setText(getDn(name)); - - String message = checkComplete(); - if (message != null) { - setMessage(message, WizardPage.ERROR); - setPageComplete(false); - } else { - setMessage("Complete", WizardPage.INFORMATION); - setPageComplete(true); - } - getContainer().updateButtons(); - } - - @Override - public void focusGained(FocusEvent event) { - } - - /** @return the error message or null if complete */ - protected String checkComplete() { - String name = commonNameTxt.getText(); - - if (name.trim().equals("")) - return "Common name must not be empty"; - Role role = userAdminWrapper.getUserAdmin().getRole(getDn(name)); - if (role != null) - return "Group " + name + " already exists"; - return null; - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) - if (baseDnCmb.getSelectionIndex() == -1) - baseDnCmb.setFocus(); - else - commonNameTxt.setFocus(); - } - } - - private Map getDns() { - return userAdminWrapper.getKnownBaseDns(true); - } - - private String getDn(String cn) { - Map dns = getDns(); - String bdn = baseDnCmb.getText(); - if (EclipseUiUtils.notEmpty(bdn)) { - Dictionary props = DirectoryConf.uriAsProperties(dns.get(bdn)); - String dn = LdapAttrs.cn.name() + "=" + cn + "," + DirectoryConf.groupBase.getValue(props) + "," + bdn; - return dn; - } - return null; - } - - private void initialiseDnCmb(Combo combo) { - Map dns = userAdminWrapper.getKnownBaseDns(true); - if (dns.isEmpty()) - throw new CmsException("No writable base dn found. Cannot create group"); - combo.setItems(dns.keySet().toArray(new String[0])); - if (dns.size() == 1) - combo.select(0); - } - } - - private Combo createGridLC(Composite parent, String label) { - Label lbl = new Label(parent, SWT.LEAD); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Combo combo = new Combo(parent, SWT.LEAD | SWT.BORDER | SWT.READ_ONLY); - combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - return combo; - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java deleted file mode 100644 index 40a446006..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java +++ /dev/null @@ -1,287 +0,0 @@ -package org.argeo.cms.e4.users.handlers; - -import java.util.Dictionary; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; -import javax.naming.ldap.Rdn; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.UiAdminUtils; -import org.argeo.cms.e4.users.UserAdminWrapper; -import org.argeo.cms.swt.CmsException; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.util.directory.DirectoryConf; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.e4.core.di.annotations.Execute; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdminEvent; - -/** Open a wizard that enables creation of a new user. */ -public class NewUser { - // private final static Log log = LogFactory.getLog(NewUser.class); - // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".newUser"; - - /* DEPENDENCY INJECTION */ - @Inject - private UserAdminWrapper userAdminWrapper; - - @Execute - public Object execute() { - NewUserWizard newUserWizard = new NewUserWizard(); - newUserWizard.setWindowTitle("User creation"); - WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), newUserWizard); - dialog.open(); - return null; - } - - private class NewUserWizard extends Wizard { - - // pages - private MainUserInfoWizardPage mainUserInfo; - - // End user fields - private Text dNameTxt, usernameTxt, firstNameTxt, lastNameTxt, primaryMailTxt, pwd1Txt, pwd2Txt; - private Combo baseDnCmb; - - public NewUserWizard() { - - } - - @Override - public void addPages() { - mainUserInfo = new MainUserInfoWizardPage(); - addPage(mainUserInfo); - String message = "Default wizard that also eases user creation tests:\n " - + "Mail and last name are automatically " - + "generated form the uid. Password are defauted to 'demo'."; - mainUserInfo.setMessage(message, WizardPage.WARNING); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public boolean performFinish() { - if (!canFinish()) - return false; - String username = mainUserInfo.getUsername(); - userAdminWrapper.beginTransactionIfNeeded(); - try { - User user = (User) userAdminWrapper.getUserAdmin().createRole(getDn(username), Role.USER); - - Dictionary props = user.getProperties(); - - String lastNameStr = lastNameTxt.getText(); - if (EclipseUiUtils.notEmpty(lastNameStr)) - props.put(LdapAttrs.sn.name(), lastNameStr); - - String firstNameStr = firstNameTxt.getText(); - if (EclipseUiUtils.notEmpty(firstNameStr)) - props.put(LdapAttrs.givenName.name(), firstNameStr); - - String cn = UserAdminUtils.buildDefaultCn(firstNameStr, lastNameStr); - if (EclipseUiUtils.notEmpty(cn)) - props.put(LdapAttrs.cn.name(), cn); - - String mailStr = primaryMailTxt.getText(); - if (EclipseUiUtils.notEmpty(mailStr)) - props.put(LdapAttrs.mail.name(), mailStr); - - char[] password = mainUserInfo.getPassword(); - user.getCredentials().put(null, password); - userAdminWrapper.commitOrNotifyTransactionStateChange(); - userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CREATED, user)); - return true; - } catch (Exception e) { - ErrorFeedback.show("Cannot create new user " + username, e); - return false; - } - } - - private class MainUserInfoWizardPage extends WizardPage implements ModifyListener { - private static final long serialVersionUID = -3150193365151601807L; - - public MainUserInfoWizardPage() { - super("Main"); - setTitle("Required Information"); - } - - @Override - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - dNameTxt = EclipseUiUtils.createGridLT(composite, "Distinguished name", this); - dNameTxt.setEnabled(false); - - baseDnCmb = createGridLC(composite, "Base DN"); - initialiseDnCmb(baseDnCmb); - baseDnCmb.addModifyListener(this); - baseDnCmb.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = -1435351236582736843L; - - @Override - public void modifyText(ModifyEvent event) { - String name = usernameTxt.getText(); - dNameTxt.setText(getDn(name)); - } - }); - - usernameTxt = EclipseUiUtils.createGridLT(composite, "Local ID", this); - usernameTxt.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = -1435351236582736843L; - - @Override - public void modifyText(ModifyEvent event) { - String name = usernameTxt.getText(); - if (name.trim().equals("")) { - dNameTxt.setText(""); - lastNameTxt.setText(""); - primaryMailTxt.setText(""); - pwd1Txt.setText(""); - pwd2Txt.setText(""); - } else { - dNameTxt.setText(getDn(name)); - lastNameTxt.setText(name.toUpperCase()); - primaryMailTxt.setText(getMail(name)); - pwd1Txt.setText("demo"); - pwd2Txt.setText("demo"); - } - } - }); - - primaryMailTxt = EclipseUiUtils.createGridLT(composite, "Email", this); - firstNameTxt = EclipseUiUtils.createGridLT(composite, "First name", this); - lastNameTxt = EclipseUiUtils.createGridLT(composite, "Last name", this); - pwd1Txt = EclipseUiUtils.createGridLP(composite, "Password", this); - pwd2Txt = EclipseUiUtils.createGridLP(composite, "Repeat password", this); - setControl(composite); - - // Initialize buttons - setPageComplete(false); - getContainer().updateButtons(); - } - - @Override - public void modifyText(ModifyEvent event) { - String message = checkComplete(); - if (message != null) { - setMessage(message, WizardPage.ERROR); - setPageComplete(false); - } else { - setMessage("Complete", WizardPage.INFORMATION); - setPageComplete(true); - } - getContainer().updateButtons(); - } - - /** @return error message or null if complete */ - protected String checkComplete() { - String name = usernameTxt.getText(); - - if (name.trim().equals("")) - return "User name must not be empty"; - Role role = userAdminWrapper.getUserAdmin().getRole(getDn(name)); - if (role != null) - return "User " + name + " already exists"; - if (!primaryMailTxt.getText().matches(UiAdminUtils.EMAIL_PATTERN)) - return "Not a valid email address"; - if (lastNameTxt.getText().trim().equals("")) - return "Specify a last name"; - if (pwd1Txt.getText().trim().equals("")) - return "Specify a password"; - if (pwd2Txt.getText().trim().equals("")) - return "Repeat the password"; - if (!pwd2Txt.getText().equals(pwd1Txt.getText())) - return "Passwords are different"; - return null; - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) - if (baseDnCmb.getSelectionIndex() == -1) - baseDnCmb.setFocus(); - else - usernameTxt.setFocus(); - } - - public String getUsername() { - return usernameTxt.getText(); - } - - public char[] getPassword() { - return pwd1Txt.getTextChars(); - } - - } - - private Map getDns() { - return userAdminWrapper.getKnownBaseDns(true); - } - - private String getDn(String uid) { - Map dns = getDns(); - String bdn = baseDnCmb.getText(); - if (EclipseUiUtils.notEmpty(bdn)) { - Dictionary props = DirectoryConf.uriAsProperties(dns.get(bdn)); - String dn = LdapAttrs.uid.name() + "=" + uid + "," + DirectoryConf.userBase.getValue(props) + "," + bdn; - return dn; - } - return null; - } - - private void initialiseDnCmb(Combo combo) { - Map dns = userAdminWrapper.getKnownBaseDns(true); - if (dns.isEmpty()) - throw new CmsException("No writable base dn found. Cannot create user"); - combo.setItems(dns.keySet().toArray(new String[0])); - if (dns.size() == 1) - combo.select(0); - } - - private String getMail(String username) { - if (baseDnCmb.getSelectionIndex() == -1) - return null; - String baseDn = baseDnCmb.getText(); - try { - LdapName name = new LdapName(baseDn); - List rdns = name.getRdns(); - return username + "@" + (String) rdns.get(1).getValue() + '.' + (String) rdns.get(0).getValue(); - } catch (InvalidNameException e) { - throw new CmsException("Unable to generate mail for " + username + " with base dn " + baseDn, e); - } - } - } - - private Combo createGridLC(Composite parent, String label) { - Label lbl = new Label(parent, SWT.LEAD); - lbl.setText(label); - lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); - Combo combo = new Combo(parent, SWT.LEAD | SWT.BORDER | SWT.READ_ONLY); - combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - return combo; - } - - /* DEPENDENCY INJECTION */ - public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) { - this.userAdminWrapper = userAdminWrapper; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/package-info.java deleted file mode 100644 index cf3db1d16..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Users management handlers. */ -package org.argeo.cms.e4.users.handlers; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/package-info.java deleted file mode 100644 index c6f14b0cf..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Users management perspective. */ -package org.argeo.cms.e4.users; \ No newline at end of file diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/CommonNameLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/CommonNameLP.java deleted file mode 100644 index 2d8db67d7..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/CommonNameLP.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.util.naming.LdapAttrs; -import org.osgi.service.useradmin.User; - -/** Simply declare a label provider that returns the common name of a user */ -public class CommonNameLP extends UserAdminAbstractLP { - private static final long serialVersionUID = 5256703081044911941L; - - @Override - public String getText(User user) { - return UserAdminUtils.getProperty(user, LdapAttrs.cn.name()); - } - - @Override - public String getToolTipText(Object element) { - return UserAdminUtils.getProperty((User) element, LdapAttrs.DN); - } - -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/DomainNameLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/DomainNameLP.java deleted file mode 100644 index e23729da8..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/DomainNameLP.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.argeo.cms.auth.UserAdminUtils; -import org.osgi.service.useradmin.User; - -/** The human friendly domain name for the corresponding user. */ -public class DomainNameLP extends UserAdminAbstractLP { - private static final long serialVersionUID = 5256703081044911941L; - - @Override - public String getText(User user) { - return UserAdminUtils.getDomainName(user); - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/MailLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/MailLP.java deleted file mode 100644 index 52d3b858f..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/MailLP.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.util.naming.LdapAttrs; -import org.osgi.service.useradmin.User; - -/** Simply declare a label provider that returns the Primary Mail of a user */ -public class MailLP extends UserAdminAbstractLP { - private static final long serialVersionUID = 8329764452141982707L; - - @Override - public String getText(User user) { - return UserAdminUtils.getProperty(user, LdapAttrs.mail.name()); - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/RoleIconLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/RoleIconLP.java deleted file mode 100644 index 8e12eeda1..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/RoleIconLP.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.argeo.api.cms.CmsContext; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.e4.users.SecurityAdminImages; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.swt.graphics.Image; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.User; - -/** Provide a bundle specific image depending on the current user type */ -public class RoleIconLP extends UserAdminAbstractLP { - private static final long serialVersionUID = 6550449442061090388L; - - @Override - public String getText(User user) { - return ""; - } - - @Override - public Image getImage(Object element) { - User user = (User) element; - String dn = user.getName(); - if (dn.endsWith(CmsConstants.SYSTEM_ROLES_BASEDN)) - return SecurityAdminImages.ICON_ROLE; - else if (user.getType() == Role.GROUP) { - String businessCategory = UserAdminUtils.getProperty(user, LdapAttrs.businessCategory); - if (businessCategory != null && businessCategory.equals(CmsContext.WORKGROUP)) - return SecurityAdminImages.ICON_WORKGROUP; - return SecurityAdminImages.ICON_GROUP; - } else - return SecurityAdminImages.ICON_USER; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java deleted file mode 100644 index 29873db2f..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; - -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.cms.swt.CmsException; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.widgets.Display; -import org.osgi.service.useradmin.User; - -/** - * Utility class that add font modifications to a column label provider - * depending on the given user properties - */ -public abstract class UserAdminAbstractLP extends ColumnLabelProvider { - private static final long serialVersionUID = 137336765024922368L; - - // private Font italic; - private Font bold; - - @Override - public Font getFont(Object element) { - // Self as bold - try { - LdapName selfUserName = UserAdminUtils.getCurrentUserLdapName(); - String userName = ((User) element).getName(); - LdapName userLdapName = new LdapName(userName); - if (userLdapName.equals(selfUserName)) { - if (bold == null) - bold = JFaceResources.getFontRegistry() - .defaultFontDescriptor().setStyle(SWT.BOLD) - .createFont(Display.getCurrent()); - return bold; - } - } catch (InvalidNameException e) { - throw new CmsException("cannot parse dn for " + element, e); - } - - // Disabled as Italic - // Node userProfile = (Node) elem; - // if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) - // return italic; - - return null; - // return super.getFont(element); - } - - @Override - public String getText(Object element) { - User user = (User) element; - return getText(user); - } - - public void setDisplay(Display display) { - // italic = JFaceResources.getFontRegistry().defaultFontDescriptor() - // .setStyle(SWT.ITALIC).createFont(display); - bold = JFaceResources.getFontRegistry().defaultFontDescriptor() - .setStyle(SWT.BOLD).createFont(Display.getCurrent()); - } - - public abstract String getText(User user); -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserDragListener.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserDragListener.java deleted file mode 100644 index 56a26244b..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserDragListener.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.dnd.DragSourceEvent; -import org.eclipse.swt.dnd.DragSourceListener; -import org.osgi.service.useradmin.User; - -/** Default drag listener to modify group and users via the UI */ -public class UserDragListener implements DragSourceListener { - private static final long serialVersionUID = -2074337775033781454L; - private final Viewer viewer; - - public UserDragListener(Viewer viewer) { - this.viewer = viewer; - } - - public void dragStart(DragSourceEvent event) { - // TODO implement finer checks - IStructuredSelection selection = (IStructuredSelection) viewer - .getSelection(); - if (selection.isEmpty() || selection.size() > 1) - event.doit = false; - else - event.doit = true; - } - - public void dragSetData(DragSourceEvent event) { - // TODO Support multiple selection - Object obj = ((IStructuredSelection) viewer.getSelection()) - .getFirstElement(); - if (obj != null) { - User user = (User) obj; - event.data = user.getName(); - } - } - - public void dragFinished(DragSourceEvent event) { - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserFilter.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserFilter.java deleted file mode 100644 index 7a7bfbf56..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserFilter.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.auth.UserAdminUtils; -import org.argeo.util.naming.LdapAttrs; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerFilter; -import org.osgi.service.useradmin.User; - -/** - * Filter user list using JFace mechanism on the client (yet on the server) side - * rather than having the UserAdmin to process the search - */ -public class UserFilter extends ViewerFilter { - private static final long serialVersionUID = 5082509381672880568L; - - private String searchString; - private boolean showSystemRole = true; - - private final String[] knownProps = { LdapAttrs.DN, LdapAttrs.cn.name(), LdapAttrs.givenName.name(), - LdapAttrs.sn.name(), LdapAttrs.uid.name(), LdapAttrs.description.name(), LdapAttrs.mail.name() }; - - public void setSearchText(String s) { - // ensure that the value can be used for matching - if (notEmpty(s)) - searchString = ".*" + s.toLowerCase() + ".*"; - else - searchString = ".*"; - } - - public void setShowSystemRole(boolean showSystemRole) { - this.showSystemRole = showSystemRole; - } - - @Override - public boolean select(Viewer viewer, Object parentElement, Object element) { - User user = (User) element; - if (!showSystemRole && user.getName().matches(".*(" + CmsConstants.SYSTEM_ROLES_BASEDN + ")")) - // UserAdminUtils.getProperty(user, LdifName.dn.name()) - // .toLowerCase().endsWith(AuthConstants.ROLES_BASEDN)) - return false; - - if (searchString == null || searchString.length() == 0) - return true; - - if (user.getName().matches(searchString)) - return true; - - for (String key : knownProps) { - String currVal = UserAdminUtils.getProperty(user, key); - if (notEmpty(currVal) && currVal.toLowerCase().matches(searchString)) - return true; - } - return false; - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserNameLP.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserNameLP.java deleted file mode 100644 index 3cd00eb2b..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserNameLP.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.argeo.cms.e4.users.providers; - -import org.osgi.service.useradmin.User; - -/** Simply declare a label provider that returns the username of a user */ -public class UserNameLP extends UserAdminAbstractLP { - private static final long serialVersionUID = 6550449442061090388L; - - @Override - public String getText(User user) { - return user.getName(); - } -} diff --git a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/package-info.java b/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/package-info.java deleted file mode 100644 index 33bef8dee..000000000 --- a/swt/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Users management content providers. */ -package org.argeo.cms.e4.users.providers; \ No newline at end of file diff --git a/swt/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi b/swt/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi index 5b250eebf..afaf71f98 100644 --- a/swt/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi +++ b/swt/rcp/org.argeo.cms.e4.rcp/argeo-companion.e4xmi @@ -6,7 +6,7 @@ - + editorArea @@ -15,7 +15,7 @@ - +