<!-- Legacy Argeo Commons platform (Eclipse 3) -->
<dependency>
- <groupId>org.argeo.commons</groupId>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
<artifactId>org.argeo.dep.cms.platform</artifactId>
- <version>${version.argeo-commons}</version>
+ <version>${version.argeo-commons-legacy}</version>
</dependency>
<dependency>
Bundle-Name: SLC Agent based on Spring\r
Bundle-RequiredExecutionEnvironment: JavaSE-1.8\r
Bundle-SymbolicName: org.argeo.slc.dep.spring\r
-Bundle-Version: 2.1.17.SNAPSHOT-r202001021027\r
+Bundle-Version: 2.1.17.SNAPSHOT-r202001040954\r
Private-Package: !*\r
SLC-Category: org.argeo.slc\r
SLC-ModularDistribution: default\r
--- /dev/null
+/target/
+/feature.xml
+/modularDistribution.csv
+/*-maven.target
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+bin.includes = feature.xml,\
+ modularDistribution.csv
--- /dev/null
+properties.1.name=org.eclipse.equinox.p2.type.category
+properties.1.value=true
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>legacy-dep</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.dep.cms.platform</artifactId>
+ <name>CMS Platform (Legacy)</name>
+ <dependencies>
+
+ <!-- Parent dependencies -->
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.dep.cms.node</artifactId>
+ <version>${version.argeo-commons}</version>
+ <type>pom</type>
+ </dependency>
+
+ <!-- RWT -->
+ <dependency>
+ <groupId>org.argeo.tp.rap.e4</groupId>
+ <artifactId>org.eclipse.rap.rwt</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.e4</groupId>
+ <artifactId>org.eclipse.core.commands</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.e4</groupId>
+ <artifactId>org.eclipse.rap.jface</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.e4</groupId>
+ <artifactId>org.eclipse.rap.filedialog</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.e4</groupId>
+ <artifactId>org.eclipse.rap.fileupload</artifactId>
+ </dependency>
+
+ <!-- Argeo Commons UI -->
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.eclipse.ui</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.eclipse.ui.rap</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms.ui</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms.ui.theme</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+
+ <!-- Eclipse 3 specific -->
+ <dependency>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>org.argeo.cms.ui.workbench</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>org.argeo.cms.ui.workbench.rap</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>org.argeo.ext.rap.ui.workbench</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ </dependency>
+
+ <!-- Misc Third Parties -->
+ <!-- <dependency> -->
+ <!-- <groupId>org.argeo.tp.apache</groupId> -->
+ <!-- <artifactId>org.apache.tika.parser</artifactId> -->
+ <!-- </dependency> -->
+ <dependency>
+ <groupId>org.argeo.tp.bouncycastle</groupId>
+ <artifactId>bcmail</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.bouncycastle</groupId>
+ <artifactId>bcpg</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.apache.ant</groupId>
+ <artifactId>org.apache.ant</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.apache.ant</groupId>
+ <artifactId>org.apache.ant.launch</artifactId>
+ </dependency>
+ <!-- <dependency> -->
+ <!-- <groupId>org.argeo.tp.misc</groupId> -->
+ <!-- <artifactId>org.quartz-scheduler.quartz</artifactId> -->
+ <!-- </dependency> -->
+ <!-- <dependency> -->
+ <!-- <groupId>org.argeo.tp.misc</groupId> -->
+ <!-- <artifactId>org.quartz-scheduler.quartz.jobs</artifactId> -->
+ <!-- </dependency> -->
+ <dependency>
+ <groupId>org.argeo.tp.javax</groupId>
+ <artifactId>javax.mail</artifactId>
+ </dependency>
+
+ <!-- Base Spring dependency -->
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.javax</groupId>
+ <artifactId>javax.el</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.extender</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.misc</groupId>
+ <artifactId>org.aspectj.weaver</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.misc</groupId>
+ <artifactId>org.aopalliance</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.aop</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.expression</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.instrument</artifactId>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.aspects</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.context.support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.jdbc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.tx</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.web.servlet</artifactId>
+ </dependency>
+
+ <!-- Equinox HTTP registry is required by Eclipse 3 but causes problem
+ with Eclipse 4 -->
+ <dependency>
+ <groupId>org.argeo.tp.equinox</groupId>
+ <artifactId>org.eclipse.equinox.http.registry</artifactId>
+ </dependency>
+
+ <!-- Eclipse Core -->
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.databinding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.databinding.beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.databinding.property</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>com.ibm.icu</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.contenttype</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.rwt.osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.jface.databinding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.jobs</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.expressions</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.core.databinding.observable</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.help</artifactId>
+ </dependency>
+
+ <!-- RAP Workbench -->
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.ui</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.ui.forms</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.ui.views</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.rap.platform</groupId>
+ <artifactId>org.eclipse.rap.ui.workbench</artifactId>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.tp</groupId>
+ <artifactId>argeo-tp-rap-e3</artifactId>
+ <version>${version.argeo-tp}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <profiles>
+ <profile>
+ <id>rpmbuild</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>prepare-source</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>a2-source</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- <plugin> -->
+ <!-- <groupId>org.apache.maven.plugins</groupId> -->
+ <!-- <artifactId>maven-dependency-plugin</artifactId> -->
+ <!-- <executions> -->
+ <!-- <execution> -->
+ <!-- <id>copy-argeo</id> -->
+ <!-- <phase>package</phase> -->
+ <!-- <goals> -->
+ <!-- <goal>copy-dependencies</goal> -->
+ <!-- </goals> -->
+ <!-- <configuration> -->
+ <!-- <includeTypes>jar</includeTypes> -->
+ <!-- <outputDirectory>${project.build.directory}/lib-argeo</outputDirectory> -->
+ <!-- <includeGroupIds>org.argeo.commons</includeGroupIds> -->
+ <!-- <excludeTransitive>true</excludeTransitive> -->
+ <!-- <excludeArtifactIds>org.argeo.dep.cms.node</excludeArtifactIds> -->
+ <!-- <includeTypes>jar</includeTypes> -->
+ <!-- <includeScope>runtime</includeScope> -->
+ <!-- <useRepositoryLayout>true</useRepositoryLayout> -->
+ <!-- </configuration> -->
+ <!-- </execution> -->
+ <!-- </executions> -->
+ <!-- </plugin> -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rpm-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>rpm-argeo</id>
+ <phase>package</phase>
+ <goals>
+ <goal>rpm</goal>
+ </goals>
+ <configuration>
+ <name>argeo-cms-platform</name>
+ <mappings>
+ <mapping>
+ <directory>/usr/share/osgi</directory>
+ <username>root</username>
+ <groupname>root</groupname>
+ <filemode>644</filemode>
+ <directoryIncluded>false</directoryIncluded>
+ <sources>
+ <source>
+ <location>${project.build.directory}/${project.artifactId}-${project.version}-a2-source</location>
+ <includes>
+ <include>**/*.jar</include>
+ </includes>
+ </source>
+ </sources>
+ </mapping>
+ <!-- <mapping> -->
+ <!-- <directory>/usr/share/osgi/org/argeo/commons/${project.artifactId}/${project.version}</directory> -->
+ <!-- <username>root</username> -->
+ <!-- <groupname>root</groupname> -->
+ <!-- <directoryIncluded>false</directoryIncluded> -->
+ <!-- <artifact /> -->
+ <!-- </mapping> -->
+ </mappings>
+ <requires>
+ <require>argeo-cms-node</require>
+ <require>argeo-cms-platform-tp</require>
+ </requires>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>rpmbuild-tp</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>prepare-source-tp</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>a2-source-tp</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- <plugin> -->
+ <!-- <groupId>org.apache.maven.plugins</groupId> -->
+ <!-- <artifactId>maven-dependency-plugin</artifactId> -->
+ <!-- <executions> -->
+ <!-- <execution> -->
+ <!-- <id>copy-tp</id> -->
+ <!-- <phase>package</phase> -->
+ <!-- <goals> -->
+ <!-- <goal>copy-dependencies</goal> -->
+ <!-- </goals> -->
+ <!-- <configuration> -->
+ <!-- <includeTypes>jar</includeTypes> -->
+ <!-- <outputDirectory>${project.build.directory}/lib-tp</outputDirectory> -->
+ <!-- <excludeGroupIds>org.argeo.commons</excludeGroupIds> -->
+ <!-- <excludeTransitive>true</excludeTransitive> -->
+ <!-- <includeTypes>jar</includeTypes> -->
+ <!-- <includeScope>runtime</includeScope> -->
+ <!-- <useRepositoryLayout>true</useRepositoryLayout> -->
+ <!-- </configuration> -->
+ <!-- </execution> -->
+ <!-- </executions> -->
+ <!-- </plugin> -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rpm-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>rpm-tp</id>
+ <phase>package</phase>
+ <goals>
+ <goal>rpm</goal>
+ </goals>
+ <configuration>
+ <name>argeo-cms-platform-tp</name>
+ <projversion>${version.argeo-tp}</projversion>
+ <mappings>
+ <mapping>
+ <directory>/usr/share/osgi</directory>
+ <username>root</username>
+ <groupname>root</groupname>
+ <filemode>644</filemode>
+ <directoryIncluded>false</directoryIncluded>
+ <sources>
+ <source>
+ <location>${project.build.directory}/${project.artifactId}-${project.version}-a2-source-tp</location>
+ <includes>
+ <include>**/*.jar</include>
+ </includes>
+ </source>
+ </sources>
+ </mapping>
+ </mappings>
+ <requires>
+ <require>argeo-cms-node-tp</require>
+ </requires>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>argeo-commons-legacy</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>legacy-dep</artifactId>
+ <name>Commons Modular Distributions (Legacy)</name>
+ <packaging>pom</packaging>
+ <modules>
+ <module>org.argeo.dep.cms.platform</module>
+ </modules>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <SLC-ModularDistribution>default</SLC-ModularDistribution>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.argeo.maven.plugins</groupId>
+ <artifactId>argeo-osgi-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-descriptors</id>
+ <goals>
+ <goal>descriptors</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>assembly-descriptors</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <attach>false</attach>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.tp.equinox</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.sdk</groupId>
+ <artifactId>org.junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <profile>
+ <id>check-osgi</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.argeo.maven.plugins</groupId>
+ <artifactId>argeo-osgi-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>check-osgi</id>
+ <phase>test</phase>
+ <goals>
+ <goal>equinox</goal>
+ </goals>
+ <configuration>
+ <onlyCheck>true</onlyCheck>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.osgi.boot</artifactId>
+ <version>${version.argeo-commons}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src" />
+ <classpathentry kind="con"
+ path="org.eclipse.pde.core.requiredPlugins" />
+ <classpathentry kind="con"
+ path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8" />
+ <classpathentry kind="output" path="bin" />
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.cms.ui.workbench.rap</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <bean id="org.argeo.cms.ui.workbench.rap.openChangePasswordDialog"
+ class="org.argeo.cms.ui.workbench.commands.OpenChangePasswordDialog"
+ scope="prototype">
+ <property name="userAdmin" ref="userAdmin" />
+ <property name="userTransaction" ref="userTransaction" />
+ <property name="keyring" ref="keyring" />
+ </bean>
+
+ <!-- RAP Specific command and corresponding service to enable open file -->
+ <bean id="org.argeo.cms.ui.workbench.openFile" class="org.argeo.eclipse.ui.specific.OpenFile"
+ scope="prototype">
+ <property name="openFileServiceId"
+ value="org.argeo.security.ui.specific.openFileService" />
+ </bean>
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+ xmlns:osgi="http://www.springframework.org/schema/osgi"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi \r
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+ http://www.springframework.org/schema/beans \r
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"\r
+ osgi:default-timeout="30000">\r
+\r
+ <reference id="userAdmin" interface="org.osgi.service.useradmin.UserAdmin" />\r
+ <reference id="userTransaction" interface="javax.transaction.UserTransaction" />\r
+ <reference id="keyring" interface="org.argeo.node.security.CryptoKeyring" />\r
+</beans:beans>\r
--- /dev/null
+changePassword=Change password
\ No newline at end of file
--- /dev/null
+changePassword=Passwort ändern
\ No newline at end of file
--- /dev/null
+changePassword=Changer de mot de passe
\ No newline at end of file
--- /dev/null
+changePassword=\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C
--- /dev/null
+Bundle-SymbolicName: org.argeo.cms.ui.workbench.rap;singleton:=true
+Bundle-Activator: org.argeo.cms.ui.workbench.rap.SecureRapActivator
+Bundle-ActivationPolicy: lazy
+
+Require-Bundle: org.eclipse.rap.ui,org.eclipse.core.runtime
+
+Import-Package: org.argeo.cms,\
+org.argeo.cms.auth,\
+org.argeo.cms.ui.workbench,\
+org.argeo.cms.ui.workbench.commands,\
+org.argeo.eclipse.ui.specific,\
+org.argeo.eclipse.spring,\
+org.argeo.node,\
+*
--- /dev/null
+<html>
+<head></head>
+<body>
+<center>
+<table height="100%">
+<tr>
+ <td style="vertical-align:middle">
+ <a
+ style="font-family:sans-serif;color:#0066CC;text-decoration:none;"
+ href="node"
+ title="Click to log in"
+ >Login...</a>
+ </td>
+</tr>
+</table>
+</center>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>
+<head></head>
+<body>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>
+<head></head>
+<body>
+<center>
+<table height="100%">
+<tr>
+ <td style="vertical-align:middle">
+ <a
+ style="font-family:sans-serif;color:#0066CC;text-decoration:none;"
+ href="javascript:location.reload(true);"
+ title="Click to log in"
+ >Login...</a>
+ </td>
+</tr>
+</table>
+</center>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<html>
+<head></head>
+<body>
+<center>
+<table height="100%">
+<tr>
+ <td style="vertical-align:middle">
+ <a
+ style="font-family:sans-serif;color:#0066CC;text-decoration:none;"
+ href="javascript:location.reload(true);"
+ title="Refresh"
+ >Refresh...</a>
+ </td>
+</tr>
+</table>
+</center>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+source.. = src/
+bin.includes = OSGI-INF/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.rap.ui.entrypoint">
+ <entrypoint
+ id="org.argeo.cms.ui.workbench.rap.secureEntryPoint"
+ class="org.argeo.cms.ui.workbench.rap.RapWorkbenchLogin"
+ path="/node"
+ brandingId="org.argeo.cms.ui.workbench.rap.defaultBranding">
+ </entrypoint>
+ <entrypoint
+ id="org.argeo.cms.ui.workbench.rap.anonymousEntryPoint"
+ class="org.argeo.cms.ui.workbench.rap.AnonymousEntryPoint"
+ path="/public"
+ brandingId="org.argeo.cms.ui.workbench.rap.defaultBranding">
+ </entrypoint>
+ <entrypoint
+ brandingId="org.argeo.cms.ui.workbench.rap.defaultBranding"
+ class="org.argeo.cms.ui.workbench.rap.SpnegoWorkbenchLogin"
+ id="org.argeo.cms.ui.workbench.rap.loginEntryPoint"
+ path="/login">
+ </entrypoint>
+<!-- <entrypoint
+ id="org.argeo.cms.ui.workbench.rap.secureEntryPoint"
+ class="org.argeo.security.ui.rap.RapWorkbenchLogin"
+ path="/login"
+ brandingId="org.argeo.cms.ui.workbench.rap.defaultBranding">
+ </entrypoint> -->
+ </extension>
+
+ <!-- COMMANDS -->
+ <extension point="org.eclipse.ui.commands">
+ <command
+ id="org.argeo.cms.ui.workbench.rap.mainMenuCommand"
+ defaultHandler="org.argeo.cms.ui.workbench.rap.commands.OpenHome"
+ name="Main">
+ </command>
+ <command
+ id="org.argeo.cms.ui.workbench.rap.openChangePasswordDialog"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="%changePassword">
+ </command>
+ <!-- Enable an "open file" action in a single sourced application -->
+ <command
+ id="org.argeo.cms.ui.workbench.openFile"
+ defaultHandler="org.argeo.eclipse.spring.SpringExtensionFactory"
+ name="OpenFile">
+ <commandParameter
+ id="param.fileName"
+ name="The name of the file to open (optional)">
+ </commandParameter>
+ <commandParameter
+ id="param.fileURI"
+ name="The URI of this file on the server">
+ </commandParameter>
+ </command>
+ </extension>
+
+ <!-- MENUS -->
+ <extension point="org.eclipse.ui.menus">
+ <!-- Main tool bar menu -->
+ <!--
+ <menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar">
+ <toolbar id="org.argeo.cms.ui.workbench.rap.userToolbar">
+ <command
+ commandId="org.argeo.cms.ui.workbench.rap.mainMenuCommand"
+ icon="icons/home.gif"
+ id="org.argeo.cms.ui.workbench.rap.mainMenu"
+ style="pulldown">
+ </command>
+ <command commandId="org.eclipse.ui.file.save"/>
+ <command commandId="org.eclipse.ui.file.saveAll"/>
+ </toolbar>
+ </menuContribution>
+ -->
+ <menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar">
+ <toolbar id="org.argeo.cms.ui.workbench.userToolbar">
+ <command
+ commandId="org.argeo.cms.ui.workbench.rap.mainMenuCommand"
+ icon="icons/home.png"
+ id="org.argeo.cms.ui.workbench.rap.mainMenu"
+ style="pulldown">
+ </command>
+ <command commandId="org.eclipse.ui.file.save" icon="icons/save.png"/>
+ <command commandId="org.eclipse.ui.file.saveAll" icon="icons/save-all.png"/>
+ </toolbar>
+ </menuContribution>
+
+ <!-- User drop down default menu -->
+ <menuContribution locationURI="menu:org.argeo.cms.ui.workbench.rap.mainMenu">
+ <!-- Managed programmatically in the RapActionBarAdvisor to enable
+ the display of the current logged-in user id -->
+ <command
+ commandId="org.argeo.cms.ui.workbench.rap.userMenuCommand"
+ icon="icons/person-logged-in.png"
+ id="org.argeo.cms.ui.workbench.rap.userMenu">
+ </command>
+ <!-- Still unused
+ <command
+ commandId="org.eclipse.ui.window.preferences"
+ icon="icons/preferences.png"/> -->
+ <command
+ commandId="org.argeo.cms.ui.workbench.rap.openChangePasswordDialog"
+ icon="icons/security.gif"
+ label="%changePassword"/>
+ <separator
+ name="org.argeo.cms.ui.workbench.rap.beforeFile"
+ visible="true">
+ </separator>
+ <command commandId="org.eclipse.ui.file.closeAll" icon="icons/close-all.png"/>
+ <command commandId="org.eclipse.ui.file.save" icon="icons/save.png"/>
+ <command commandId="org.eclipse.ui.file.saveAll" icon="icons/save-all.png"/>
+
+ <!--<command commandId="org.eclipse.ui.views.showView"/>-->
+ <command commandId="org.eclipse.ui.perspectives.showPerspective"/>
+ <separator
+ name="org.argeo.cms.ui.workbench.rap.beforeExit"
+ visible="true">
+ </separator>
+ <command commandId="org.eclipse.ui.file.exit" icon="icons/exit.png"/>
+ </menuContribution>
+ </extension>
+
+ <!-- SERVICE HANDLERS -->
+ <extension point="org.eclipse.rap.ui.serviceHandler">
+ <!-- Rap specific service handler to enable file download over the internet-->
+ <serviceHandler
+ class="org.argeo.eclipse.ui.specific.OpenFileService"
+ id="org.argeo.security.ui.specific.openFileService">
+ </serviceHandler>
+ </extension>
+
+ <!-- ACTIVITIES -->
+ <extension
+ point="org.eclipse.ui.activities">
+ <activity
+ description="Anonymous"
+ id="org.argeo.cms.ui.workbench.rap.anonymousActivity"
+ name="Anonymous">
+ <enabledWhen>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=anonymous,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </enabledWhen>
+ </activity>
+ <activity
+ description="Not anonymous"
+ id="org.argeo.cms.ui.workbench.rap.notAnonymousActivity"
+ name="NotAnonymous">
+ <enabledWhen>
+ <not>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=anonymous,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </not>
+ </enabledWhen>
+ </activity>
+ <activityPatternBinding
+ activityId="org.argeo.cms.ui.workbench.rap.notAnonymousActivity"
+ pattern="org.argeo.cms.ui.workbench.rap/org.argeo.cms.ui.workbench.rap.userMenuCommand"/>
+ <activityPatternBinding
+ activityId="org.argeo.cms.ui.workbench.rap.notAnonymousActivity"
+ pattern="org.argeo.cms.ui.workbench.rap/org.eclipse.ui.window.preferences"/>
+ <activityPatternBinding
+ activityId="org.argeo.cms.ui.workbench.rap.notAnonymousActivity"
+ pattern="org.argeo.cms.ui.workbench.rap/org.argeo.cms.ui.workbench.rap.openChangePasswordDialog"/>
+ </extension>
+
+ <!-- BRANDINGS -->
+ <extension
+ point="org.eclipse.rap.ui.branding">
+ <branding
+ id="org.argeo.cms.ui.workbench.rap.defaultBranding"
+ themeId="org.eclipse.rap.rwt.theme.Default"
+ title="Argeo Web UI"
+ favicon="branding/favicon.ico">
+ </branding>
+ <!-- we need a servlet with this name j_spring_security_logout
+ for the logout filter -->
+ <branding
+ id="org.argeo.cms.ui.workbench.rap.logoutBranding"
+ title="Argeo Logout"
+ favicon="branding/favicon.ico"
+ body="branding/empty.html">
+ </branding>
+ </extension>
+</plugin>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>argeo-commons-legacy</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.cms.ui.workbench.rap</artifactId>
+ <name>CMS Workbench RAP</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>org.argeo.cms.ui.workbench</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ </dependency>
+ <!-- RAP specific -->
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.eclipse.ui.rap</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.argeo.tp</groupId>
+ <artifactId>argeo-tp-rap-e3</artifactId>
+ <version>${version.argeo-tp}</version>
+ <type>pom</type>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap;
+
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.application.EntryPoint;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * RAP entry point which authenticates the subject as anonymous, for public
+ * unauthenticated access.
+ */
+public class AnonymousEntryPoint implements EntryPoint {
+ private final static Log log = LogFactory.getLog(AnonymousEntryPoint.class);
+
+ /**
+ * How many seconds to wait before invalidating the session if the user has
+ * not yet logged in.
+ */
+ private Integer sessionTimeout = 5 * 60;
+
+ @Override
+ public int createUI() {
+ RWT.getRequest().getSession().setMaxInactiveInterval(sessionTimeout);
+
+ // if (log.isDebugEnabled())
+ // log.debug("Anonymous THREAD=" + Thread.currentThread().getId()
+ // + ", sessionStore=" + RWT.getSessionStore().getId());
+
+ final Display display = PlatformUI.createDisplay();
+ Subject subject = new Subject();
+
+ final LoginContext loginContext;
+ try {
+ loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS,
+ subject);
+ loginContext.login();
+ } catch (LoginException e1) {
+ throw new CmsException("Cannot initialize login context", e1);
+ }
+
+ // identify after successful login
+ if (log.isDebugEnabled())
+ log.debug("Authenticated " + subject);
+ final String username = subject.getPrincipals().iterator().next()
+ .getName();
+
+ // Logout callback when the display is disposed
+ display.disposeExec(new Runnable() {
+ public void run() {
+ log.debug("Display disposed");
+ logout(loginContext, username);
+ }
+ });
+
+ //
+ // RUN THE WORKBENCH
+ //
+ Integer returnCode = null;
+ try {
+ returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+ public Integer run() {
+ RapWorkbenchAdvisor workbenchAdvisor = new RapWorkbenchAdvisor(
+ null);
+ int result = PlatformUI.createAndRunWorkbench(display,
+ workbenchAdvisor);
+ return new Integer(result);
+ }
+ });
+ logout(loginContext, username);
+ if (log.isTraceEnabled())
+ log.trace("Return code " + returnCode);
+ } finally {
+ display.dispose();
+ }
+ return 1;
+ }
+
+ private void logout(LoginContext loginContext, String username) {
+ try {
+ loginContext.logout();
+ log.info("Logged out " + (username != null ? username : "")
+ + " (THREAD=" + Thread.currentThread().getId() + ")");
+ } catch (LoginException e) {
+ log.error("Erorr when logging out", e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap;
+
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.ui.workbench.commands.OpenHomePerspective;
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.Command;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.commands.ICommandService;
+
+/** Eclipse rap specific action bar advisor */
+public class RapActionBarAdvisor extends ActionBarAdvisor {
+ private final static String ID_BASE = SecureRapActivator.ID;
+ // private final static Log log = LogFactory
+ // .getLog(SecureActionBarAdvisor.class);
+
+ /** Null means anonymous */
+ private String username = null;
+
+ // private IAction logoutAction;
+ // private IWorkbenchAction openPerspectiveDialogAction;
+ // private IWorkbenchAction showViewMenuAction;
+ // private IWorkbenchAction preferences;
+ private IWorkbenchAction saveAction;
+ private IWorkbenchAction saveAllAction;
+
+ // private IWorkbenchAction closeAllAction;
+
+ public RapActionBarAdvisor(IActionBarConfigurer configurer, String username) {
+ super(configurer);
+ this.username = username;
+ }
+
+ protected void makeActions(IWorkbenchWindow window) {
+ // preferences = ActionFactory.PREFERENCES.create(window);
+ // register(preferences);
+ // openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
+ // .create(window);
+ // register(openPerspectiveDialogAction);
+ // showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window);
+ // register(showViewMenuAction);
+ //
+ // // logout
+ // logoutAction = ActionFactory.QUIT.create(window);
+ // // logoutAction = createLogoutAction();
+ // register(logoutAction);
+ //
+ // Save semantics
+ saveAction = ActionFactory.SAVE.create(window);
+ register(saveAction);
+ saveAllAction = ActionFactory.SAVE_ALL.create(window);
+ register(saveAllAction);
+ // closeAllAction = ActionFactory.CLOSE_ALL.create(window);
+ // register(closeAllAction);
+
+ }
+
+ protected void fillMenuBar(IMenuManager menuBar) {
+ // MenuManager fileMenu = new MenuManager("&File",
+ // IWorkbenchActionConstants.M_FILE);
+ // MenuManager editMenu = new MenuManager("&Edit",
+ // IWorkbenchActionConstants.M_EDIT);
+ // MenuManager windowMenu = new MenuManager("&Window",
+ // IWorkbenchActionConstants.M_WINDOW);
+ //
+ // menuBar.add(fileMenu);
+ // menuBar.add(editMenu);
+ // menuBar.add(windowMenu);
+ // // Add a group marker indicating where action set menus will appear.
+ // menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+ //
+ // // File
+ // fileMenu.add(saveAction);
+ // fileMenu.add(saveAllAction);
+ // fileMenu.add(closeAllAction);
+ // fileMenu.add(new
+ // GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+ // fileMenu.add(new Separator());
+ // fileMenu.add(logoutAction);
+ //
+ // // Edit
+ // editMenu.add(preferences);
+ //
+ // // Window
+ // windowMenu.add(openPerspectiveDialogAction);
+ // windowMenu.add(showViewMenuAction);
+ }
+
+ @Override
+ protected void fillCoolBar(ICoolBarManager coolBar) {
+ // Add a command which label is the display name of the current
+ // logged-in user
+ if (username != null) {
+ ICommandService cmdService = (ICommandService) getActionBarConfigurer()
+ .getWindowConfigurer().getWorkbenchConfigurer()
+ .getWorkbench().getService(ICommandService.class);
+ Category userMenus = cmdService.getCategory(ID_BASE + ".userMenus");
+ if (!userMenus.isDefined())
+ userMenus.define("User Menus", "User related menus");
+ Command userMenu = cmdService.getCommand(ID_BASE
+ + ".userMenuCommand");
+ if (userMenu.isDefined())
+ userMenu.undefine();
+ userMenu.define(CurrentUser.getDisplayName(), "User menu actions",
+ userMenus);
+ // userMenu.define(username, "User menu actions", userMenus);
+
+ userMenu.setHandler(new OpenHomePerspective());
+
+ // userToolbar.add(new UserMenuAction());
+ // coolBar.add(userToolbar);
+ } else {// anonymous
+ IToolBarManager userToolbar = new ToolBarManager(SWT.FLAT
+ | SWT.RIGHT);
+ // userToolbar.add(logoutAction);
+ coolBar.add(userToolbar);
+ }
+ // IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT |
+ // SWT.RIGHT);
+ // saveToolbar.add(saveAction);
+ // saveToolbar.add(saveAllAction);
+ // coolBar.add(saveToolbar);
+ }
+
+ // class UserMenuAction extends Action implements IWorkbenchAction {
+ //
+ // public UserMenuAction() {
+ // super(username, IAction.AS_DROP_DOWN_MENU);
+ // // setMenuCreator(new UserMenu());
+ // }
+ //
+ // @Override
+ // public String getId() {
+ // return "org.argeo.cms.ui.workbench.rap.userMenu";
+ // }
+ //
+ // @Override
+ // public void dispose() {
+ // }
+ //
+ // }
+
+ // class UserMenu implements IMenuCreator {
+ // private Menu menu;
+ //
+ // public Menu getMenu(Control parent) {
+ // Menu menu = new Menu(parent);
+ // addActionToMenu(menu, logoutAction);
+ // return menu;
+ // }
+ //
+ // private void addActionToMenu(Menu menu, IAction action) {
+ // ActionContributionItem item = new ActionContributionItem(action);
+ // item.fill(menu, -1);
+ // }
+ //
+ // public void dispose() {
+ // if (menu != null) {
+ // menu.dispose();
+ // }
+ // }
+ //
+ // public Menu getMenu(Menu parent) {
+ // // Not use
+ // return null;
+ // }
+ //
+ // }
+
+ // protected IAction createLogoutAction() {
+ // Subject subject = Subject.getSubject(AccessController.getContext());
+ // final String username = subject.getPrincipals().iterator().next()
+ // .getName();
+ //
+ // IAction logoutAction = new Action() {
+ // public String getId() {
+ // return SecureRapActivator.ID + ".logoutAction";
+ // }
+ //
+ // public String getText() {
+ // return "Logout " + username;
+ // }
+ //
+ // public void run() {
+ // // try {
+ // // Subject subject = SecureRapActivator.getLoginContext()
+ // // .getSubject();
+ // // String subjectStr = subject.toString();
+ // // subject.getPrincipals().clear();
+ // // SecureRapActivator.getLoginContext().logout();
+ // // log.info(subjectStr + " logged out");
+ // // } catch (LoginException e) {
+ // // log.error("Error when logging out", e);
+ // // }
+ // // SecureEntryPoint.logout(username);
+ // // PlatformUI.getWorkbench().close();
+ // // try {
+ // // RWT.getRequest().getSession().setMaxInactiveInterval(1);
+ // // } catch (Exception e) {
+ // // if (log.isTraceEnabled())
+ // // log.trace("Error when invalidating session", e);
+ // // }
+ // }
+ //
+ // };
+ // return logoutAction;
+ // }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+/** Eclipse RAP specific window advisor */
+public class RapWindowAdvisor extends WorkbenchWindowAdvisor {
+
+ private String username;
+
+ public RapWindowAdvisor(IWorkbenchWindowConfigurer configurer,
+ String username) {
+ super(configurer);
+ this.username = username;
+ }
+
+ @Override
+ public ActionBarAdvisor createActionBarAdvisor(
+ IActionBarConfigurer configurer) {
+ return new RapActionBarAdvisor(configurer, username);
+ }
+
+ public void preWindowOpen() {
+ IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+ configurer.setShowCoolBar(true);
+ configurer.setShowMenuBar(false);
+ configurer.setShowStatusLine(false);
+ configurer.setShowPerspectiveBar(true);
+ configurer.setTitle("Argeo Web UI"); //$NON-NLS-1$
+ // Full screen, see
+ // http://wiki.eclipse.org/RAP/FAQ#How_to_create_a_fullscreen_application
+ configurer.setShellStyle(SWT.NO_TRIM);
+ Rectangle bounds = Display.getCurrent().getBounds();
+ configurer.setInitialSize(new Point(bounds.width, bounds.height));
+
+ // Handle window resize in Rap 2.1+ see
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417254
+ Display.getCurrent().addListener(SWT.Resize, new Listener() {
+ private static final long serialVersionUID = 2970912561866704526L;
+
+ @Override
+ public void handleEvent(Event event) {
+ Rectangle bounds = event.display.getBounds();
+ IWorkbenchWindow iww = getWindowConfigurer().getWindow()
+ .getWorkbench().getActiveWorkbenchWindow();
+ iww.getShell().setBounds(bounds);
+ }
+ });
+ }
+
+ @Override
+ public void postWindowCreate() {
+ Shell shell = getWindowConfigurer().getWindow().getShell();
+ shell.setMaximized(true);
+ }
+
+ @Override
+ public void postWindowOpen() {
+ String defaultPerspective = getWindowConfigurer()
+ .getWorkbenchConfigurer().getWorkbench()
+ .getPerspectiveRegistry().getDefaultPerspective();
+ if (defaultPerspective == null) {
+ IWorkbenchWindow window = getWindowConfigurer().getWindow();
+ if (window == null)
+ return;
+
+ IWorkbenchAction openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
+ .create(window);
+ openPerspectiveDialogAction.run();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap;
+
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.application.IWorkbenchConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+/** Eclipse RAP specific workbench advisor */
+public class RapWorkbenchAdvisor extends WorkbenchAdvisor {
+ public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
+ public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore";
+
+ private String initialPerspective = System.getProperty(
+ INITIAL_PERSPECTIVE_PROPERTY, null);
+
+ private String username;
+
+ public RapWorkbenchAdvisor(String username) {
+ this.username = username;
+ }
+
+ @Override
+ public void initialize(IWorkbenchConfigurer configurer) {
+ super.initialize(configurer);
+ Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty(
+ SAVE_AND_RESTORE_PROPERTY, "false"));
+ configurer.setSaveAndRestore(saveAndRestore);
+ }
+
+ public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
+ IWorkbenchWindowConfigurer configurer) {
+ return new RapWindowAdvisor(configurer, username);
+ }
+
+ public String getInitialWindowPerspectiveId() {
+ if (initialPerspective != null) {
+ // check whether this user can see the declared perspective
+ // (typically the perspective won't be listed if this user doesn't
+ // have the right to see it)
+ IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
+ .getPerspectiveRegistry()
+ .findPerspectiveWithId(initialPerspective);
+ if (pd == null)
+ return null;
+ }
+ return initialPerspective;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.rap;
+
+import java.security.PrivilegedAction;
+import java.util.Locale;
+
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.cms.util.LoginEntryPoint;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+public class RapWorkbenchLogin extends LoginEntryPoint {
+ // private final static Log log =
+ // LogFactory.getLog(RapWorkbenchLogin.class);
+
+ /** Override to provide an application specific workbench advisor */
+ protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) {
+ return new RapWorkbenchAdvisor(username);
+ }
+
+ @Override
+ public int createUI() {
+ JavaScriptExecutor jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
+ int returnCode;
+ try {
+ returnCode = super.createUI();
+ } finally {
+ // always reload
+ // TODO optimise?
+ jsExecutor.execute("location.reload()");
+ }
+ return returnCode;
+ }
+
+ @Override
+ protected int postLogin() {
+ Subject subject = getSubject();
+ final Display display = Display.getCurrent();
+ if (subject.getPrincipals(X500Principal.class).isEmpty()) {
+ RWT.getClient().getService(JavaScriptExecutor.class).execute("location.reload()");
+ }
+ //
+ // RUN THE WORKBENCH
+ //
+ Integer returnCode = null;
+ try {
+ returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+ public Integer run() {
+ int result = createAndRunWorkbench(display, CurrentUser.getUsername(subject));
+ return new Integer(result);
+ }
+ });
+ // explicit workbench closing
+ logout();
+ } finally {
+ display.dispose();
+ }
+ return returnCode;
+ }
+
+ protected int createAndRunWorkbench(Display display, String username) {
+ RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username);
+ return PlatformUI.createAndRunWorkbench(display, workbenchAdvisor);
+ }
+
+ @Override
+ protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
+ SelectionListener loginSelectionListener) {
+// Button loginButton = new Button(credentialsBlock, SWT.PUSH);
+// loginButton.setText(CmsMsg.login.lead(selectedLocale));
+// loginButton.setLayoutData(CmsUtils.fillWidth());
+// loginButton.addSelectionListener(loginSelectionListener);
+ }
+
+ @Override
+ protected Display createDisplay() {
+ return PlatformUI.createDisplay();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/** Configure Equinox login context from the bundle context. */
+public class SecureRapActivator implements BundleActivator {
+ public final static String ID = "org.argeo.cms.ui.workbench.rap";
+
+ private static BundleContext bundleContext;
+
+ public void start(BundleContext bc) throws Exception {
+ bundleContext = bc;
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ bundleContext = null;
+ }
+
+ public static BundleContext getBundleContext() {
+ return bundleContext;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.rap;
+
+import java.security.PrivilegedAction;
+import java.util.Locale;
+
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.cms.util.LoginEntryPoint;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+public class SpnegoWorkbenchLogin extends LoginEntryPoint {
+ // private final static Log log =
+ // LogFactory.getLog(RapWorkbenchLogin.class);
+
+ /** Override to provide an application specific workbench advisor */
+ protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) {
+ return new RapWorkbenchAdvisor(username);
+ }
+
+ @Override
+ public int createUI() {
+ HttpServletRequest request = RWT.getRequest();
+ String authorization = request.getHeader(HEADER_AUTHORIZATION);
+ if (authorization == null || !authorization.startsWith("Negotiate")) {
+ HttpServletResponse response = RWT.getResponse();
+ response.setStatus(401);
+ response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate");
+ response.setDateHeader("Date", System.currentTimeMillis());
+ response.setDateHeader("Expires", System.currentTimeMillis() + (24 * 60 * 60 * 1000));
+ response.setHeader("Accept-Ranges", "bytes");
+ response.setHeader("Connection", "Keep-Alive");
+ response.setHeader("Keep-Alive", "timeout=5, max=97");
+ // response.setContentType("text/html; charset=UTF-8");
+ }
+
+ int returnCode;
+ returnCode = super.createUI();
+ return returnCode;
+ }
+
+ @Override
+ protected int postLogin() {
+ Subject subject = getSubject();
+ final Display display = Display.getCurrent();
+ if (subject.getPrincipals(X500Principal.class).isEmpty()) {
+ RWT.getClient().getService(JavaScriptExecutor.class).execute("location.reload()");
+ }
+ //
+ // RUN THE WORKBENCH
+ //
+ Integer returnCode = null;
+ try {
+ returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+ public Integer run() {
+ int result = createAndRunWorkbench(display, CurrentUser.getUsername(subject));
+ return new Integer(result);
+ }
+ });
+ // explicit workbench closing
+ logout();
+ } finally {
+ display.dispose();
+ }
+ return returnCode;
+ }
+
+ protected int createAndRunWorkbench(Display display, String username) {
+ RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username);
+ return PlatformUI.createAndRunWorkbench(display, workbenchAdvisor);
+ }
+
+ @Override
+ protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
+ SelectionListener loginSelectionListener) {
+// Button loginButton = new Button(credentialsBlock, SWT.PUSH);
+// loginButton.setText(CmsMsg.login.lead(selectedLocale));
+// loginButton.setLayoutData(CmsUtils.fillWidth());
+// loginButton.addSelectionListener(loginSelectionListener);
+ }
+
+ @Override
+ protected Display createDisplay() {
+ return PlatformUI.createDisplay();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap.commands;
+
+import org.argeo.cms.ui.workbench.UserHomePerspective;
+import org.argeo.cms.ui.workbench.util.CommandUtils;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Default action of the user menu */
+public class OpenHome extends AbstractHandler {
+ private final static String PROP_OPEN_HOME_CMD_ID = "org.argeo.ui.openHomeCommandId";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ String defaultCmdId = System.getProperty(PROP_OPEN_HOME_CMD_ID, "");
+ if (!"".equals(defaultCmdId.trim()))
+ CommandUtils.callCommand(defaultCmdId);
+ else {
+ try {
+ String defaultPerspective = HandlerUtil.getActiveWorkbenchWindow(event).getWorkbench()
+ .getPerspectiveRegistry().getDefaultPerspective();
+ HandlerUtil.getActiveSite(event).getWorkbenchWindow()
+ .openPage(defaultPerspective != null ? defaultPerspective : UserHomePerspective.ID, null);
+ } catch (WorkbenchException e) {
+ ErrorFeedback.show("Cannot open home perspective", e);
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.rap.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+
+/** Default action of the user menu */
+public class UserMenu extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ return null;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src" />
+ <classpathentry kind="con"
+ path="org.eclipse.pde.core.requiredPlugins" />
+ <classpathentry kind="con"
+ path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8" />
+ <classpathentry kind="output" path="bin" />
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.cms.ui.workbench</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <!-- USERS CRUDS -->
+ <bean id="newUser" class="org.argeo.cms.ui.workbench.internal.useradmin.commands.NewUser"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+ <bean id="deleteUsers"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.commands.DeleteUsers"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+ <bean id="userBatchUpdate"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.commands.UserBatchUpdate"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+ <!-- GROUPS CRUDS -->
+ <bean id="newGroup" class="org.argeo.cms.ui.workbench.internal.useradmin.commands.NewGroup"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+ <bean id="deleteGroups"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.commands.DeleteGroups"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+
+ <!-- TRANSACTIONS -->
+ <bean id="userTransactionHandler"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.commands.UserTransactionHandler"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+
+ <!-- DATA EXPLORER -->
+ <bean id="addRemoteRepository"
+ class="org.argeo.cms.ui.workbench.internal.jcr.commands.AddRemoteRepository">
+ <property name="repositoryFactory" ref="repositoryFactory" />
+ <property name="nodeRepository" ref="nodeRepository" />
+ <property name="keyring" ref="keyring" />
+ </bean>
+
+ <bean id="addPrivileges" class="org.argeo.cms.ui.workbench.internal.jcr.commands.AddPrivileges">
+ <property name="userAdmin" ref="userAdmin" />
+ </bean>
+ <bean id="removePrivileges"
+ class="org.argeo.cms.ui.workbench.internal.jcr.commands.RemovePrivileges">
+ <!-- <property name="userAdmin" ref="userAdmin" /> -->
+ </bean>
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+ <bean id="userTransactionProvider"\r
+ class="org.argeo.cms.ui.workbench.internal.useradmin.providers.UserTransactionProvider"\r
+ scope="singleton" lazy-init="false">\r
+ <property name="userTransaction" ref="userTransaction" />\r
+ </bean>\r
+\r
+ <bean id="userAdminWrapper"\r
+ class="org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper"\r
+ scope="singleton" lazy-init="false">\r
+ <property name="userTransaction" ref="userTransaction" />\r
+ <property name="userAdmin" ref="userAdmin" />\r
+ <property name="userAdminServiceReference" ref="userAdmin" />\r
+ </bean>\r
+\r
+ <bean id="repositoryRegister" class="org.argeo.cms.ui.jcr.DefaultRepositoryRegister" />\r
+\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+ xmlns:osgi="http://www.springframework.org/schema/osgi"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi \r
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+ http://www.springframework.org/schema/beans \r
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"\r
+ osgi:default-timeout="30000">\r
+\r
+ <!-- JCR -->\r
+ <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory" />\r
+ <reference id="keyring" interface="org.argeo.node.security.CryptoKeyring" />\r
+ <list id="repositories" interface="javax.jcr.Repository"\r
+ cardinality="0..N">\r
+ <listener ref="repositoryRegister" bind-method="register"\r
+ unbind-method="unregister" />\r
+ </list>\r
+\r
+ <reference id="nodeRepository" interface="javax.jcr.Repository"\r
+ filter="(cn=home)" />\r
+ \r
+ <reference id="nodeInstance" interface="org.argeo.node.NodeInstance" />\r
+\r
+ <reference id="nodeFileSystemProvider" interface="java.nio.file.spi.FileSystemProvider"\r
+ filter="(service.pid=org.argeo.node.fsProvider)" />\r
+\r
+ <!-- UserAdmin -->\r
+ <reference id="userAdmin" interface="org.osgi.service.useradmin.UserAdmin" />\r
+ <reference id="userTransaction" interface="javax.transaction.UserTransaction" />\r
+\r
+\r
+ <reference id="secureLogger" interface="org.argeo.node.ArgeoLogger"\r
+ cardinality="0..1" />\r
+ <reference id="defaultCallbackHandler" interface="javax.security.auth.callback.CallbackHandler" />\r
+\r
+</beans:beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <!-- SECURITY -->
+ <!-- Editors -->
+ <bean id="userEditor"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+
+ <bean id="groupEditor"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ <property name="repository" ref="nodeRepository" />
+ <property name="nodeInstance" ref="nodeInstance" />
+ </bean>
+
+ <!-- Views -->
+ <bean id="usersView"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.parts.UsersView"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+ <bean id="groupsView"
+ class="org.argeo.cms.ui.workbench.internal.useradmin.parts.GroupsView"
+ scope="prototype">
+ <property name="userAdminWrapper" ref="userAdminWrapper" />
+ </bean>
+
+
+ <!-- DATA EXPLORER -->
+ <!-- Editors -->
+ <bean id="genericJcrQueryEditor" class="org.argeo.cms.ui.workbench.jcr.GenericJcrQueryEditor"
+ scope="prototype">
+ <property name="nodeRepository" ref="nodeRepository" />
+ </bean>
+ <bean id="defaultNodeEditor" class="org.argeo.cms.ui.workbench.jcr.DefaultNodeEditor"
+ scope="prototype">
+ </bean>
+ <!-- Views -->
+ <bean id="jcrBrowserView" class="org.argeo.cms.ui.workbench.jcr.JcrBrowserView"
+ scope="prototype">
+ <property name="repositoryRegister" ref="repositoryRegister" />
+ <property name="repositoryFactory" ref="repositoryFactory" />
+ <property name="nodeRepository" ref="nodeRepository" />
+ <property name="keyring" ref="keyring" />
+ </bean>
+ <bean id="nodeFsBrowserView" class="org.argeo.cms.ui.workbench.jcr.NodeFsBrowserView"
+ scope="prototype">
+ <property name="nodeFileSystemProvider" ref="nodeFileSystemProvider" />
+ <!-- <property name="keyring" ref="keyring" /> -->
+ </bean>
+
+ <!-- LOGGERS -->
+ <bean id="logView" class="org.argeo.cms.ui.workbench.useradmin.LogView"
+ scope="prototype">
+ <property name="argeoLogger" ref="secureLogger" />
+ </bean>
+ <bean id="adminLogView" class="org.argeo.cms.ui.workbench.useradmin.AdminLogView"
+ scope="prototype">
+ <property name="argeoLogger" ref="secureLogger" />
+ </bean>
+</beans>
--- /dev/null
+search=Finden
\ No newline at end of file
--- /dev/null
+search=Search
\ No newline at end of file
--- /dev/null
+Bundle-SymbolicName: org.argeo.cms.ui.workbench;singleton:=true
+Bundle-Activator: org.argeo.cms.ui.workbench.WorkbenchUiPlugin
+Bundle-ActivationPolicy: lazy
+
+Require-Bundle: org.eclipse.core.runtime,\
+org.eclipse.core.commands
+
+Import-Package: org.argeo.cms.auth,\
+org.argeo.cms,\
+org.argeo.cms.ui,\
+org.argeo.eclipse.spring,\
+org.argeo.eclipse.ui.utils,\
+org.eclipse.core.runtime.jobs,\
+org.eclipse.jface.window,\
+org.eclipse.swt,\
+org.eclipse.swt.widgets,\
+org.eclipse.ui.services,\
+org.osgi.*;version=0.0.0,\
+org.springframework.core,\
+org.springframework.beans.factory,\
+org.springframework.core.io.support,\
+!org.eclipse.core.runtime,\
+*
+
+
+# org.argeo.eclipse.ui.workbench;resolution:=optional,\
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ icons/,\
+ plugin.xml
+additional.bundles = org.apache.commons.httpclient
--- /dev/null
+argeo.keyring.secreteKeyLength=256
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.perspectives">
+ <perspective
+ id="org.argeo.cms.ui.workbench.adminSecurityPerspective"
+ class="org.argeo.cms.ui.workbench.SecurityAdminPerspective"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/platform:/plugin/org.argeo.cms.ui.theme/icons/group.png"
+ name="Security">
+ </perspective>
+ <perspective
+ id="org.argeo.cms.ui.workbench.userHomePerspective"
+ class="org.argeo.cms.ui.workbench.UserHomePerspective"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/platform:/plugin/org.argeo.cms.ui.theme/icons/home.png"
+ name="Home">
+ </perspective>
+ <perspective
+ id="org.argeo.cms.ui.workbench.adminMaintenancePerspective"
+ class="org.argeo.cms.ui.workbench.MaintenancePerspective"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/platform:/plugin/org.argeo.cms.ui.theme/icons/maintenance.gif"
+ name="Maintenance">
+ </perspective>
+ <perspective
+ id="org.argeo.cms.ui.workbench.osgiPerspective"
+ class="org.argeo.cms.ui.workbench.OsgiExplorerPerspective"
+ name="Monitoring"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/platform:/plugin/org.argeo.cms.ui.theme/icons/osgi_explorer.gif">
+ </perspective>
+ <perspective
+ id="org.argeo.cms.ui.workbench.jcrBrowserPerspective"
+ class="org.argeo.cms.ui.workbench.JcrBrowserPerspective"
+ name="Data Explorer"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/nodes.gif">
+ </perspective>
+ </extension>
+
+ <!-- Definition of the OSGI perspective -->
+ <extension point="org.eclipse.ui.perspectiveExtensions">
+ <perspectiveExtension targetID="org.argeo.cms.ui.workbench.osgiPerspective">
+ <view
+ id="org.argeo.cms.ui.workbench.cmsSessionsView"
+ minimized="false"
+ ratio="0.5"
+ relationship="left"
+ relative="org.eclipse.ui.editorss"/>
+ <view
+ id="org.argeo.cms.ui.workbench.modulesView"
+ minimized="false"
+ relationship="stack"
+ relative="org.argeo.cms.ui.workbench.cmsSessionsView"/>
+ <view
+ id="org.argeo.cms.ui.workbench.bundlesView"
+ minimized="false"
+ relationship="stack"
+ relative="org.argeo.cms.ui.workbench.modulesView"/>
+ <view
+ id="org.argeo.cms.ui.workbench.multiplePackagesView"
+ minimized="false"
+ relationship="stack"
+ relative="org.argeo.cms.ui.workbench.bundlesView"/>
+ </perspectiveExtension>
+ </extension>
+
+
+ <!-- VIEWS -->
+ <extension
+ point="org.eclipse.ui.views">
+ <!-- Security -->
+ <view
+ id="org.argeo.cms.ui.workbench.usersView"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/person.png"
+ name="Users"
+ restorable="true">
+ </view>
+ <view
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png"
+ id="org.argeo.cms.ui.workbench.groupsView"
+ name="Groups"
+ restorable="false">
+ </view>
+ <!-- Home -->
+ <view
+ id="org.argeo.cms.ui.workbench.userProfile"
+ class="org.argeo.cms.ui.workbench.useradmin.UserProfile"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/person-logged-in.png"
+ name="Profile"
+ restorable="true">
+ </view>
+ <!-- Maintenance -->
+ <view
+ id="org.argeo.cms.ui.workbench.logView"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ name="Log"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/log.gif"
+ restorable="true">
+ </view>
+ <view
+ id="org.argeo.cms.ui.workbench.adminLogView"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ name="Admin Log"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/adminLog.gif"
+ restorable="true">
+ </view>
+ <!-- OSGi Monitor -->
+ <view
+ name="Modules"
+ id="org.argeo.cms.ui.workbench.modulesView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/service_published.gif"
+ class="org.argeo.cms.ui.workbench.osgi.ModulesView">
+ </view>
+ <view
+ name="CMS Session"
+ id="org.argeo.cms.ui.workbench.cmsSessionsView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/service_published.gif"
+ class="org.argeo.cms.ui.workbench.osgi.CmsSessionsView">
+ </view>
+ <view
+ name="Bundles"
+ id="org.argeo.cms.ui.workbench.bundlesView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/bundles.gif"
+ class="org.argeo.cms.ui.workbench.osgi.BundlesView">
+ </view>
+ <view
+ name="Multiple Packages"
+ id="org.argeo.cms.ui.workbench.multiplePackagesView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/node.gif"
+ class="org.argeo.cms.ui.workbench.osgi.MultiplePackagesView">
+ </view>
+ <!-- Data Explorer -->
+ <view
+ name="JCR"
+ id="org.argeo.cms.ui.workbench.jcrBrowserView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/browser.gif"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory">
+ </view>
+ <view
+ name="Files"
+ id="org.argeo.cms.ui.workbench.nodeFsBrowserView"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/browser.gif"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory">
+ </view>
+ </extension>
+
+ <!-- EDITORS -->
+ <extension
+ point="org.eclipse.ui.editors">
+ <!-- Security -->
+ <editor
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ id="org.argeo.cms.ui.workbench.userEditor"
+ name="User"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/person.png"
+ default="false">
+ </editor>
+ <editor
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ id="org.argeo.cms.ui.workbench.groupEditor"
+ name="User"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png"
+ default="false">
+ </editor>
+ <!-- Data Explorer -->
+ <editor
+ name="JCR Query"
+ id="org.argeo.cms.ui.workbench.genericJcrQueryEditor"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/query.png"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ default="false">
+ </editor>
+ <editor
+ name="Node Editor"
+ id="org.argeo.cms.ui.workbench.defaultNodeEditor"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/query.png"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ default="false">
+ </editor>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.commands">
+ <!-- User CRUD -->
+ <command
+ id="org.argeo.cms.ui.workbench.newUser"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="New User">
+ </command>
+ <command
+ id="org.argeo.cms.ui.workbench.deleteUsers"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="Delete User">
+ </command>
+ <command
+ id="org.argeo.cms.ui.workbench.userBatchUpdate"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="User batch update">
+ </command>
+ <!-- Group CRUD -->
+ <command
+ id="org.argeo.cms.ui.workbench.newGroup"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="New Group">
+ </command>
+ <command
+ id="org.argeo.cms.ui.workbench.deleteGroups"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="Delete Group">
+ </command>
+ <!-- Transaction -->
+ <command
+ id="org.argeo.cms.ui.workbench.userTransactionHandler"
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ name="Manage a user transaction">
+ <commandParameter
+ id="param.commandId"
+ name="begin, commit or rollback">
+ </commandParameter>
+ </command>
+ <!-- Force the refresh when the various listener are not enough -->
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.useradmin.commands.ForceRefresh"
+ id="org.argeo.cms.ui.workbench.forceRefresh"
+ name="Force Refresh">
+ </command>
+ <!-- Data Explorer -->
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.commands.OpenEditor"
+ id="org.argeo.cms.ui.workbench.openEditor"
+ name="Open an editor given its ID">
+ <commandParameter
+ id="param.jcrNodePath"
+ name="Node path">
+ </commandParameter>
+ <!-- The path to the corresponding node if needed. -->
+ <commandParameter
+ id="param.jcrNodePath"
+ name="Node path">
+ </commandParameter>
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.GetNodeSize"
+ id="org.argeo.cms.ui.workbench.getNodeSize"
+ name="Get node size">
+ </command>
+ <command
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ id="org.argeo.cms.ui.workbench.addRemoteRepository"
+ name="Add remote JCR repository">
+ <!-- <commandParameter
+ id="param.repositoryUri"
+ name="Repository URI">
+ </commandParameter> -->
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.RemoveRemoteRepository"
+ id="org.argeo.cms.ui.workbench.removeRemoteRepository"
+ name="Remove remote JCR repository">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.AddFolderNode"
+ id="org.argeo.cms.ui.workbench.addFolderNode"
+ name="Create a new folder">
+ </command>
+ <command
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ id="org.argeo.cms.ui.workbench.addPrivileges"
+ name="Add Privileges">
+ </command>
+ <command
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ id="org.argeo.cms.ui.workbench.removePrivileges"
+ name="Remove Privileges">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.CreateWorkspace"
+ id="org.argeo.cms.ui.workbench.createWorkspace"
+ name="Create a new workspace">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.Refresh"
+ id="org.argeo.cms.ui.workbench.refresh"
+ name="Refresh">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.DeleteNodes"
+ id="org.argeo.cms.ui.workbench.deleteNodes"
+ name="Delete nodes">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.UploadFiles"
+ id="org.argeo.cms.ui.workbench.uploadFiles"
+ name="Upload files">
+ </command>
+ <!-- <command
+ defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+ id="org.argeo.cms.ui.workbench.openFile"
+ name="Open current file">
+ </command> -->
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.DumpNode"
+ id="org.argeo.cms.ui.workbench.dumpNode"
+ name="Dump Current Selected Node">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.RenameNode"
+ id="org.argeo.cms.ui.workbench.renameNode"
+ name="Rename Current Selected Node">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.ConfigurableNodeDump"
+ id="org.argeo.cms.ui.workbench.nodeConfigurableDump"
+ name="Configurable dump of the selected Node">
+ </command>
+ <command
+ defaultHandler="org.argeo.cms.ui.workbench.internal.jcr.commands.SortChildNodes"
+ id="org.argeo.cms.ui.workbench.sortChildNodes"
+ name="Sort node tree">
+ <!-- FIXME: default value does not work -->
+ <state
+ id="org.argeo.cms.ui.workbench.sortChildNodes.toggleState"
+ class="org.eclipse.ui.handlers.RegistryToggleState:true" >
+ <!-- <class class="org.eclipse.jface.commands.ToggleState">
+ <parameter
+ name="default"
+ value="true" />
+ </class> -->
+ </state>
+ </command>
+ <!-- Utility to provide sub menues when we don't want to define a default command for this menu -->
+ <command
+ id="org.argeo.cms.ui.workbench.doNothing"
+ defaultHandler="org.argeo.cms.ui.workbench.commands.DoNothing"
+ name="Open menu">
+ </command>
+ </extension>
+
+ <!-- MENU CONTRIBUTIONS -->
+ <extension
+ point="org.eclipse.ui.menus">
+ <!-- Main tool bar menu
+ <menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar">
+ <toolbar id="org.argeo.cms.ui.workbench.userToolbar">
+ <command
+ commandId="org.argeo.cms.ui.workbench.rap.mainMenuCommand"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/home.png"
+ id="org.argeo.cms.ui.workbench.rap.mainMenu"
+ style="pulldown">
+ </command>
+ <command commandId="org.eclipse.ui.file.save" icon="platform:/plugin/org.argeo.cms.ui.theme/icons/save.png"/>
+ <command commandId="org.eclipse.ui.file.saveAll" icon="platform:/plugin/org.argeo.cms.ui.theme/icons/save-all.png"/>
+ </toolbar>
+ </menuContribution>
+ -->
+ <menuContribution
+ locationURI="toolbar:org.argeo.cms.ui.workbench.userToolbar?after=org.eclipse.ui.file.saveAll">
+ <!-- Transaction management -->
+ <command
+ commandId="org.argeo.cms.ui.workbench.userTransactionHandler"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/commit.gif"
+ label="Commit Transaction"
+ style="push"
+ tooltip="Commit a user transaction">
+ <parameter name="param.commandId" value="transaction.commit" />
+ <visibleWhen>
+ <with variable="org.argeo.cms.ui.workbench.userTransactionState">
+ <equals value="status.active" />
+ </with>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.userTransactionHandler"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/rollback.gif"
+ label="Rollback Transaction"
+ style="push"
+ tooltip="Abandon current changes and rollback to the latest commited version">
+ <parameter name="param.commandId" value="transaction.rollback" />
+ <visibleWhen>
+ <with variable="org.argeo.cms.ui.workbench.userTransactionState">
+ <equals value="status.active" />
+ </with>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+
+ <!-- UsersView specific toolbar menu -->
+ <menuContribution
+ locationURI="toolbar:org.argeo.cms.ui.workbench.usersView">
+ <command
+ commandId="org.argeo.cms.ui.workbench.deleteUsers"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/delete.png"
+ label="Delete"
+ tooltip="Delete selected users">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.forceRefresh"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/refresh.png"
+ label="Refresh"
+ tooltip="Force the full refresh of the user list">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.newUser"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/add.png"
+ label="Add"
+ tooltip="Create a new user">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.userBatchUpdate"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/batch.gif"
+ label="Update users"
+ tooltip="Perform maintenance activities on a list of chosen users">
+ </command>
+ </menuContribution>
+
+ <!-- GroupsView specific toolbar menu -->
+ <menuContribution
+ locationURI="toolbar:org.argeo.cms.ui.workbench.groupsView">
+ <command
+ commandId="org.argeo.cms.ui.workbench.deleteGroups"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/delete.png"
+ label="Delete Group"
+ tooltip="Delete selected groups">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.forceRefresh"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/refresh.png"
+ label="Refresh list"
+ tooltip="Force the full refresh of the group list">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.newGroup"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/add.png"
+ label="Add Group"
+ tooltip="Create a new group">
+ </command>
+ </menuContribution>
+
+ <!-- Browser view specific menu -->
+ <menuContribution
+ locationURI="menu:org.argeo.cms.ui.workbench.jcrBrowserView">
+ <!-- See bug 149 -->
+ <!-- <command
+ commandId="org.argeo.cms.ui.workbench.openGenericJcrQueryEditor"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/query.png"
+ style="push">
+ </command> -->
+ <command
+ commandId="org.argeo.cms.ui.workbench.addRemoteRepository"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/addRepo.gif"
+ style="push">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.sortChildNodes"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/sort.gif"
+ style="toggle"
+ label="Sort child nodes"
+ tooltip="NOTE: displaying unsorted nodes will enhance overall performances">
+ </command>
+ </menuContribution>
+ <!-- Browser view popup context menu -->
+ <menuContribution
+ locationURI="popup:org.argeo.cms.ui.workbench.jcrBrowserView">
+ <command
+ commandId="org.argeo.cms.ui.workbench.refresh"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/refresh.png"
+ style="push">
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.addFolderNode"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/addFolder.gif"
+ label="Add Folder..."
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem">
+ </instanceof>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem">
+ </instanceof>
+ </or>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.addPrivileges"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/addPrivileges.gif"
+ label="Add Privileges..."
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem">
+ </instanceof>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem">
+ </instanceof>
+ </or>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.removePrivileges"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/removePrivileges.gif"
+ label="Remove Privileges..."
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem">
+ </instanceof>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem">
+ </instanceof>
+ </or>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.createWorkspace"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/addWorkspace.png"
+ label="Create Workspace..."
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.RepositoryElem">
+ </instanceof>
+ </or>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.deleteNodes"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/remove.gif"
+ label="Delete Nodes"
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem" />
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem" />
+ </or>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.uploadFiles"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/import_fs.png"
+ style="push"
+ tooltip="Upload files from the local file sytem">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem" />
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem" />
+ </or>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.addRemoteRepository"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/addRepo.gif"
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.RepositoriesElem" />
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.RepositoryElem" />
+ </or>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.removeRemoteRepository"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/remove.gif"
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.RemoteRepositoryElem" />
+ </or>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.getNodeSize"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/getSize.gif"
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <or>
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem" />
+ <instanceof
+ value="org.argeo.cms.ui.jcr.model.WorkspaceElem" />
+ </or>
+ </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.dumpNode"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/dumpNode.gif"
+ label="Dump Node"
+ style="push">
+ <visibleWhen>
+ <iterate> <and>
+ <instanceof value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem"></instanceof>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and> </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.renameNode"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/rename.gif"
+ label="Rename..."
+ style="push">
+ <visibleWhen>
+ <iterate> <and>
+ <instanceof value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem"></instanceof>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and> </iterate>
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.argeo.cms.ui.workbench.nodeConfigurableDump"
+ icon="platform:/plugin/org.argeo.cms.ui.theme/icons/dumpNode.gif"
+ label="Configurable dump..."
+ style="push">
+ <visibleWhen>
+ <iterate>
+ <and>
+ <instanceof value="org.argeo.cms.ui.jcr.model.SingleJcrNodeElem"></instanceof>
+ <with variable="activeMenuSelection"><count value="1"/></with>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+
+ </extension>
+
+ <!-- SERVICES -->
+ <extension
+ point="org.eclipse.ui.services">
+ <sourceProvider
+ id="org.argeo.cms.ui.workbench.userTransactionProvider"
+ provider="org.argeo.eclipse.spring.SpringExtensionFactory" >
+ <variable
+ name="org.argeo.cms.ui.workbench.userTransactionState"
+ priorityLevel="workbench">
+ </variable>
+ </sourceProvider>
+ <sourceProvider
+ provider="org.argeo.cms.ui.workbench.util.RolesSourceProvider">
+ <variable
+ name="org.argeo.cms.ui.workbench.rolesVariable"
+ priorityLevel="workbench">
+ </variable>
+ </sourceProvider>
+ </extension>
+
+ <!-- ACTIVITIES -->
+ <extension
+ point="org.eclipse.ui.activities">
+
+ <!-- Admin -->
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.osgiPerspective"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.adminActivity">
+ </activityPatternBinding>
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.jcrBrowserPerspective"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.adminActivity">
+ </activityPatternBinding>
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.adminMaintenancePerspective"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.adminActivity">
+ </activityPatternBinding>
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.adminLogView"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.adminActivity">
+ </activityPatternBinding>
+
+ <!-- UserAdmin -->
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.adminSecurityPerspective"
+ activityId="org.argeo.cms.ui.workbench.userAdminActivity"
+ isEqualityPattern="true">
+ </activityPatternBinding>
+
+ <!-- Users -->
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.userHomePerspective"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.userActivity">
+ </activityPatternBinding>
+ <activityPatternBinding
+ pattern="org.argeo.cms.ui.workbench/org.argeo.cms.ui.workbench.userProfile"
+ isEqualityPattern="true"
+ activityId="org.argeo.cms.ui.workbench.userActivity">
+ </activityPatternBinding>
+
+
+ <!-- Activity declaration -->
+ <activity
+ description="Authenticated users"
+ id="org.argeo.cms.ui.workbench.userActivity"
+ name="User">
+ <enabledWhen>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=user,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </enabledWhen>
+ </activity>
+ <activity
+ description="Admins"
+ id="org.argeo.cms.ui.workbench.adminActivity"
+ name="Admin">
+ <enabledWhen>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=admin,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </enabledWhen>
+ </activity>
+ <activity
+ description="User Admins"
+ id="org.argeo.cms.ui.workbench.userAdminActivity"
+ name="User Admin">
+ <enabledWhen>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=userAdmin,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </enabledWhen>
+ </activity>
+ <activity
+ description="Non admins"
+ id="org.argeo.cms.ui.workbench.notAdminActivity"
+ name="Not Admin">
+ <enabledWhen>
+ <not>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="cn=admin,ou=roles,ou=node" />
+ </iterate>
+ </with>
+ </not>
+ </enabledWhen>
+ </activity>
+ <activity
+ description="Non remote"
+ id="org.argeo.cms.ui.workbench.notRemoteActivity"
+ name="NonRemote">
+ <enabledWhen>
+ <not>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="ROLE_REMOTE" />
+ </iterate>
+ </with>
+ </not>
+ </enabledWhen>
+ </activity>
+ </extension>
+
+ <!-- STARTUP -->
+ <extension point="org.eclipse.ui.startup">
+ <startup class="org.argeo.cms.ui.workbench.internal.useradmin.PartStateChanged"/>
+ </extension>
+</plugin>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>argeo-commons-legacy</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.cms.ui.workbench</artifactId>
+ <name>CMS Workbench</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms.ui</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.eclipse.ui.rap</artifactId>
+ <version>${version.argeo-commons}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.core</artifactId>
+ </dependency>
+
+ <!-- Eclipse 3 -->
+ <dependency>
+ <groupId>org.argeo.tp</groupId>
+ <artifactId>argeo-tp-rap-e3</artifactId>
+ <version>${version.argeo-tp}</version>
+ <type>pom</type>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.spring;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
+
+/** Provides base method for executing code with system authorization. */
+abstract class AbstractSystemExecution {
+ private final static Log log = LogFactory.getLog(AbstractSystemExecution.class);
+ private final Subject subject = new Subject();
+
+ /** Authenticate the calling thread */
+ protected void authenticateAsSystem() {
+ ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
+ lc.login();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot login as system", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(origClassLoader);
+ }
+ if (log.isTraceEnabled())
+ log.trace("System authenticated");
+ }
+
+ protected void deauthenticateAsSystem() {
+ ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
+ lc.logout();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot logout as system", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(origClassLoader);
+ }
+ }
+
+ protected Subject getSubject() {
+ return subject;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.spring;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+import org.eclipse.gemini.blueprint.context.DependencyInitializationAwareBeanPostProcessor;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.support.AbstractBeanFactory;
+import org.springframework.beans.factory.support.SecurityContextProvider;
+import org.springframework.beans.factory.support.SimpleSecurityContextProvider;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Executes with a system authentication the instantiation and initialization
+ * methods of the application context where it has been defined.
+ */
+public class AuthenticatedApplicationContextInitialization extends
+ AbstractSystemExecution implements
+ DependencyInitializationAwareBeanPostProcessor, ApplicationContextAware {
+ /** If non empty, restricts to these beans */
+ private List<String> beanNames = new ArrayList<String>();
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (beanNames.size() == 0 || beanNames.contains(beanName))
+ authenticateAsSystem();
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (beanNames.size() == 0 || beanNames.contains(beanName))
+ deauthenticateAsSystem();
+ return bean;
+ }
+
+ public void setBeanNames(List<String> beanNames) {
+ this.beanNames = beanNames;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ if (applicationContext.getAutowireCapableBeanFactory() instanceof AbstractBeanFactory) {
+ final AbstractBeanFactory beanFactory = ((AbstractBeanFactory) applicationContext
+ .getAutowireCapableBeanFactory());
+ // retrieve subject's access control context
+ // and set it as the bean factory security context
+ Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ SecurityContextProvider scp = new SimpleSecurityContextProvider(
+ AccessController.getContext());
+ beanFactory.setSecurityContextProvider(scp);
+ return null;
+ }
+ });
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.spring;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+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 Log log = LogFactory
+ .getLog(SimpleRoleRegistration.class);
+
+ private String role;
+ private List<String> roles = new ArrayList<String>();
+ private UserAdmin userAdmin;
+ private UserTransaction 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 CmsException("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 CmsException("Badly formatted role name " + name, e);
+ }
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public void setRoles(List<String> roles) {
+ this.roles = roles;
+ }
+
+ public void setUserAdmin(UserAdmin userAdminService) {
+ this.userAdmin = userAdminService;
+ }
+
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.spring.osgi;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Logs the name and version of an OSGi bundle based on its
+ * {@link BundleContext}.
+ */
+public class OsgiModuleLabel {
+ private final static Log log = LogFactory.getLog(OsgiModuleLabel.class);
+
+ private Bundle bundle;
+
+ public OsgiModuleLabel() {
+ }
+
+ /** Sets without logging. */
+ public OsgiModuleLabel(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ /**
+ * Retrieved bundle from a bundle context and logs it. Typically to be set
+ * as a Spring bean.
+ */
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundle = bundleContext.getBundle();
+ log.info(msg());
+ }
+
+ public String msg() {
+ String name = bundle.getHeaders().get(Constants.BUNDLE_NAME).toString();
+ String symbolicName = bundle.getSymbolicName();
+ String version = bundle.getVersion().toString();
+ return name + " v" + version + " (" + symbolicName + ")";
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench;
+
+/** Centralize the declaration of Workbench specific CSS Styles */
+public interface CmsWorkbenchStyles {
+
+ // Specific People layouting
+ String WORKBENCH_FORM_TEXT = "workbench_form_text";
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.cms.ui.workbench.jcr.NodeFsBrowserView;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Base perspective for the Jcr browser */
+public class JcrBrowserPerspective implements IPerspectiveFactory {
+
+ public void createInitialLayout(IPageLayout layout) {
+ layout.setEditorAreaVisible(true);
+ IFolderLayout upperLeft = layout.createFolder(WorkbenchUiPlugin.PLUGIN_ID + ".upperLeft", IPageLayout.LEFT,
+ 0.4f, layout.getEditorArea());
+ upperLeft.addView(JcrBrowserView.ID);
+ upperLeft.addView(NodeFsBrowserView.ID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import org.argeo.cms.ui.workbench.useradmin.AdminLogView;
+import org.argeo.cms.ui.workbench.useradmin.UserProfile;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** First draft of a maintenance perspective. Not yet used */
+public class MaintenancePerspective implements IPerspectiveFactory {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".adminMaintenancePerspective";
+
+ public void createInitialLayout(IPageLayout layout) {
+ String editorArea = layout.getEditorArea();
+ layout.setEditorAreaVisible(true);
+ layout.setFixed(false);
+
+ IFolderLayout bottom = layout.createFolder("bottom",
+ IPageLayout.BOTTOM, 0.50f, editorArea);
+ bottom.addView(AdminLogView.ID);
+
+ IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
+ 0.30f, editorArea);
+ left.addView(UserProfile.ID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** OSGi explorer perspective (to be enriched declaratively) */
+public class OsgiExplorerPerspective implements IPerspectiveFactory {
+
+ public void createInitialLayout(IPageLayout layout) {
+ layout.setEditorAreaVisible(true);
+ layout.setFixed(false);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.GroupsView;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UsersView;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Default perspective to manage users and groups */
+public class SecurityAdminPerspective implements IPerspectiveFactory {
+ public void createInitialLayout(IPageLayout layout) {
+ String editorArea = layout.getEditorArea();
+ layout.setEditorAreaVisible(true);
+ layout.setFixed(false);
+
+ IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.3f, editorArea);
+ IFolderLayout right = layout.createFolder("right", IPageLayout.RIGHT, 0.5f, editorArea);
+ left.addView(UsersView.ID);
+ right.addView(GroupsView.ID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import org.argeo.cms.ui.workbench.jcr.NodeFsBrowserView;
+import org.argeo.cms.ui.workbench.useradmin.UserProfile;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Home perspective for the current user */
+public class UserHomePerspective implements IPerspectiveFactory {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".userHomePerspective";
+
+ public void createInitialLayout(IPageLayout layout) {
+ String editorArea = layout.getEditorArea();
+ layout.setEditorAreaVisible(true);
+ layout.setFixed(false);
+
+ IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.40f, editorArea);
+ left.addView(NodeFsBrowserView.ID);
+ left.addView(UserProfile.ID);
+ // left.addView(LogView.ID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.widgets.auth.DefaultLoginDialog;
+import org.eclipse.core.runtime.ILogListener;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/** The activator class controls the plug-in life cycle */
+public class WorkbenchUiPlugin extends AbstractUIPlugin implements ILogListener {
+ private final static Log log = LogFactory.getLog(WorkbenchUiPlugin.class);
+
+ // The plug-in ID
+ public final static String PLUGIN_ID = "org.argeo.cms.ui.workbench"; //$NON-NLS-1$
+ public final static String THEME_PLUGIN_ID = "org.argeo.cms.ui.theme"; //$NON-NLS-1$
+
+ private ResourceBundle messages;
+ private static BundleContext bundleContext;
+
+ public static InheritableThreadLocal<Display> display = new InheritableThreadLocal<Display>() {
+
+ @Override
+ protected Display initialValue() {
+ return Display.getCurrent();
+ }
+ };
+
+ final static String CONTEXT_KEYRING = "KEYRING";
+
+ private CallbackHandler defaultCallbackHandler;
+ private ServiceRegistration<CallbackHandler> defaultCallbackHandlerReg;
+
+ // The shared instance
+ private static WorkbenchUiPlugin plugin;
+
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ bundleContext = context;
+ defaultCallbackHandler = new DefaultCallbackHandler();
+ defaultCallbackHandlerReg = context.registerService(CallbackHandler.class, defaultCallbackHandler, null);
+
+ plugin = this;
+ messages = ResourceBundle.getBundle(PLUGIN_ID + ".messages");
+ Platform.addLogListener(this);
+ if (log.isTraceEnabled())
+ log.trace("Eclipse logging now directed to standard logging");
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ bundleContext = null;
+ defaultCallbackHandlerReg.unregister();
+ }
+
+ public static BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ /*
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static WorkbenchUiPlugin getDefault() {
+ return plugin;
+ }
+
+ protected class DefaultCallbackHandler implements CallbackHandler {
+ public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ // if (display != null) // RCP
+ Display displayToUse = display.get();
+ if (displayToUse == null)// RCP
+ displayToUse = Display.getDefault();
+ displayToUse.syncExec(new Runnable() {
+ public void run() {
+ DefaultLoginDialog dialog = new DefaultLoginDialog(display.get().getActiveShell());
+ try {
+ dialog.handle(callbacks);
+ } catch (IOException e) {
+ throw new CmsException("Cannot open dialog", e);
+ }
+ }
+ });
+ // else {// RAP
+ // DefaultLoginDialog dialog = new DefaultLoginDialog();
+ // dialog.handle(callbacks);
+ // }
+ }
+
+ }
+
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(THEME_PLUGIN_ID, path);
+ }
+
+ /** Returns the internationalized label for the given key */
+ public static String getMessage(String key) {
+ try {
+ return getDefault().messages.getString(key);
+ } catch (NullPointerException npe) {
+ log.warn(key + " not found.");
+ return key;
+ }
+ }
+
+ /**
+ * Gives access to the internationalization message bundle. Returns null in case
+ * this UiPlugin is not started (for JUnit tests, by instance)
+ */
+ public static ResourceBundle getMessagesBundle() {
+ if (getDefault() != null)
+ // To avoid NPE
+ return getDefault().messages;
+ else
+ return null;
+ }
+
+ public void logging(IStatus status, String plugin) {
+ Log pluginLog = LogFactory.getLog(plugin);
+ Integer severity = status.getSeverity();
+ if (severity == IStatus.ERROR)
+ pluginLog.error(status.getMessage(), status.getException());
+ else if (severity == IStatus.WARNING)
+ pluginLog.warn(status.getMessage(), status.getException());
+ else if (severity == IStatus.INFO)
+ pluginLog.info(status.getMessage(), status.getException());
+ else if (severity == IStatus.CANCEL)
+ if (pluginLog.isDebugEnabled())
+ pluginLog.debug(status.getMessage(), status.getException());
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.commands;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+
+/** Utilitary command to enable sub menus in various toolbars. Does nothing */
+public class DoNothing extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".doNothing";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.commands;
+
+import static org.argeo.cms.CmsMsg.changePassword;
+import static org.argeo.cms.CmsMsg.currentPassword;
+import static org.argeo.cms.CmsMsg.newPassword;
+import static org.argeo.cms.CmsMsg.passwordChanged;
+import static org.argeo.cms.CmsMsg.repeatNewPassword;
+import static org.eclipse.jface.dialogs.IMessageProvider.INFORMATION;
+
+import java.security.AccessController;
+import java.util.Arrays;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.node.security.CryptoKeyring;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/** Open the change password dialog */
+public class OpenChangePasswordDialog extends AbstractHandler {
+ private final static Log log = LogFactory.getLog(OpenChangePasswordDialog.class);
+ private UserAdmin userAdmin;
+ private UserTransaction userTransaction;
+ private CryptoKeyring keyring = null;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ChangePasswordDialog dialog = new ChangePasswordDialog(HandlerUtil.getActiveShell(event), userAdmin);
+ if (dialog.open() == Dialog.OK) {
+ MessageDialog.openInformation(HandlerUtil.getActiveShell(event), passwordChanged.lead(),
+ passwordChanged.lead());
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void changePassword(char[] oldPassword, char[] newPassword) {
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ String name = subject.getPrincipals(X500Principal.class).iterator().next().toString();
+ LdapName dn;
+ try {
+ dn = new LdapName(name);
+ } catch (InvalidNameException e) {
+ throw new CmsException("Invalid user dn " + name, e);
+ }
+ User user = (User) userAdmin.getRole(dn.toString());
+ if (!user.hasCredential(null, oldPassword))
+ throw new CmsException("Invalid password");
+ if (Arrays.equals(newPassword, new char[0]))
+ throw new CmsException("New password empty");
+ try {
+ userTransaction.begin();
+ user.getCredentials().put(null, newPassword);
+ if (keyring != null) {
+ keyring.changePassword(oldPassword, newPassword);
+ // TODO change secret keys in the CMS session
+ }
+ userTransaction.commit();
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new CmsException("Cannot change password", e);
+ }
+ }
+
+ class ChangePasswordDialog extends TitleAreaDialog {
+ private static final long serialVersionUID = -6963970583882720962L;
+ private Text oldPassword, newPassword1, newPassword2;
+
+ public ChangePasswordDialog(Shell parentShell, UserAdmin securityService) {
+ super(parentShell);
+ }
+
+ protected Point getInitialSize() {
+ return new Point(400, 450);
+ }
+
+ 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));
+ oldPassword = createLP(composite, currentPassword.lead());
+ newPassword1 = createLP(composite, newPassword.lead());
+ newPassword2 = createLP(composite, repeatNewPassword.lead());
+
+ setMessage(changePassword.lead(), INFORMATION);
+ parent.pack();
+ oldPassword.setFocus();
+ return composite;
+ }
+
+ @Override
+ protected void okPressed() {
+ try {
+ if (!newPassword1.getText().equals(newPassword2.getText()))
+ throw new CmsException("New passwords are different");
+ changePassword(oldPassword.getTextChars(), newPassword1.getTextChars());
+ close();
+ } catch (Exception e) {
+ ErrorFeedback.show("Cannot change password", e);
+ }
+ }
+
+ /** Creates label and password. */
+ protected Text createLP(Composite parent, String label) {
+ new Label(parent, SWT.NONE).setText(label);
+ Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD | SWT.BORDER);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ return text;
+ }
+
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(changePassword.lead());
+ }
+ }
+
+ public void setUserAdmin(UserAdmin userAdmin) {
+ this.userAdmin = userAdmin;
+ }
+
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+ public void setKeyring(CryptoKeyring keyring) {
+ this.keyring = keyring;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.commands;
+
+import javax.jcr.Node;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.JcrQueryEditorInput;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.NodeEditorInput;
+import org.argeo.cms.ui.workbench.jcr.DefaultNodeEditor;
+import org.argeo.cms.ui.workbench.jcr.GenericJcrQueryEditor;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Open a {@link Node} editor of a specific type given the node path */
+public class OpenEditor extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".openEditor";
+
+ public final static String PARAM_PATH = "param.jcrNodePath";
+ public final static String PARAM_EDITOR_ID = "param.editorId";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String editorId = event.getParameter(PARAM_EDITOR_ID);
+ try {
+ IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow(
+ event).getActivePage();
+ if (DefaultNodeEditor.ID.equals(editorId)) {
+ String path = event.getParameter(PARAM_PATH);
+ NodeEditorInput nei = new NodeEditorInput(path);
+ activePage.openEditor(nei, DefaultNodeEditor.ID);
+ } else if (GenericJcrQueryEditor.ID.equals(editorId)) {
+ JcrQueryEditorInput editorInput = new JcrQueryEditorInput(
+ GenericJcrQueryEditor.ID, null);
+ activePage.openEditor(editorInput, editorId);
+ }
+ } catch (PartInitException e) {
+ throw new EclipseUiException(
+ "Cannot open editor of ID " + editorId, e);
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.commands;
+
+import org.argeo.cms.ui.workbench.UserHomePerspective;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Default action of the user menu */
+public class OpenHomePerspective extends AbstractHandler {
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ try {
+ HandlerUtil.getActiveSite(event).getWorkbenchWindow()
+ .openPage(UserHomePerspective.ID, null);
+ } catch (WorkbenchException e) {
+ ErrorFeedback.show("Cannot open home perspective", e);
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal;
+
+/** Constants used across the application. */
+@Deprecated
+public interface WorkbenchConstants {
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.eclipse.ui.dialogs.SingleValue;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * 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 extends AbstractHandler {
+
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".addFolderNode";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ TreeParent treeParentNode = null;
+ Node jcrParentNode = null;
+
+ 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 null;
+
+ 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"));
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.AddPrivilegeWizard;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.osgi.service.useradmin.UserAdmin;
+
+/** Open a dialog to add privileges on the selected node to a chosen group */
+public class AddPrivileges extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".addPrivileges";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdmin userAdmin;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ TreeParent treeParentNode = null;
+ Node jcrParentNode = null;
+
+ 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 null;
+
+ try {
+ String targetPath = jcrParentNode.getPath();
+ AddPrivilegeWizard wizard = new AddPrivilegeWizard(
+ jcrParentNode.getSession(), targetPath, userAdmin);
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), wizard);
+ dialog.open();
+ return null;
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Unable to retrieve "
+ + "path or JCR session to add privilege on "
+ + jcrParentNode, re);
+ }
+ } else {
+ ErrorFeedback.show("Cannot add privileges");
+ }
+ return null;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdmin(UserAdmin userAdmin) {
+ this.userAdmin = userAdmin;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.net.URI;
+import java.util.Hashtable;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.ArgeoTypes;
+import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
+import org.argeo.cms.ui.workbench.util.CommandUtils;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.NodeUtils;
+import org.argeo.node.security.Keyring;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+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 extends AbstractHandler implements WorkbenchConstants, ArgeoNames {
+
+ private RepositoryFactory repositoryFactory;
+ private Repository nodeRepository;
+ private Keyring keyring;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog(Display.getDefault().getActiveShell());
+ if (dlg.open() == Dialog.OK) {
+ CommandUtils.callCommand(Refresh.ID);
+ }
+ return 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<String, String> params = new Hashtable<String, String>();
+ params.put(NodeConstants.LABELED_URI, checkedUriStr);
+ Repository repository = repositoryFactory.getRepository(params);
+ if (username.getText().trim().equals("")) {// anonymous
+ // FIXME make it more generic
+ session = repository.login("main");
+ } 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 = NodeUtils.getUserHome(nodeSession);
+
+ Node remote = home.hasNode(ARGEO_REMOTE) ? home.getNode(ARGEO_REMOTE) : home.addNode(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(ARGEO_URI, uri.getText());
+ remoteRepository.setProperty(ARGEO_USER_ID, username.getText());
+ nodeSession.save();
+ if (saveInKeyring.getSelection()) {
+ String pwdPath = remoteRepository.getPath() + '/' + 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+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.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * First draft of a wizard that enable configurable recursive dump of the
+ * current selected Node (Only one at a time). Enable among other to export
+ * children Nodes and to choose to export binaries or not. It is useful to
+ * retrieve business data from live systems to prepare migration or test locally
+ */
+public class ConfigurableNodeDump extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".nodeConfigurableDump";
+
+ private final static DateFormat df = new SimpleDateFormat(
+ "yyyy-MM-dd_HH-mm");
+
+ public final static int EXPORT_NODE = 0;
+ public final static int EXPORT_CHILDREN = 1;
+ public final static int EXPORT_GRAND_CHILDREN = 2;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+ if (selection == null || !(selection instanceof IStructuredSelection))
+ return null;
+
+ Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+ if (lst.hasNext()) {
+ Object element = lst.next();
+ if (element instanceof SingleJcrNodeElem) {
+ SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
+ Node node = sjn.getNode();
+
+ ConfigureDumpWizard wizard = new ConfigureDumpWizard(
+ HandlerUtil.getActiveShell(event),
+ "Import Resource CSV");
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), wizard);
+ int result = dialog.open();
+
+ if (result == Window.OK) {
+
+ String dateVal = df.format(new GregorianCalendar()
+ .getTime());
+ try {
+
+ Path tmpDirPath = Files.createTempDirectory(dateVal
+ + "-NodeDump-");
+ List<Node> toExport = retrieveToExportNodes(node,
+ wizard.currExportType);
+
+ for (Node currNode : toExport) {
+ FileOutputStream fos;
+ String fileName = wizard.prefix
+ + JcrUtils.replaceInvalidChars(currNode
+ .getName()) + "_" + dateVal
+ + ".xml";
+ File currFile = new File(tmpDirPath.toString()
+ + "/" + fileName);
+ currFile.createNewFile();
+ fos = new FileOutputStream(currFile);
+ node.getSession().exportSystemView(
+ currNode.getPath(), fos,
+ !wizard.includeBinaries, false);
+ fos.flush();
+ fos.close();
+ }
+ } catch (RepositoryException e) {
+ throw new EclipseUiException(
+ "Unable to perform SystemExport on " + node, e);
+ } catch (IOException e) {
+ throw new EclipseUiException("Unable to SystemExport "
+ + node, e);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private List<Node> retrieveToExportNodes(Node node, int currExportType)
+ throws RepositoryException {
+ List<Node> nodes = new ArrayList<Node>();
+ switch (currExportType) {
+ case EXPORT_NODE:
+ nodes.add(node);
+ return nodes;
+ case EXPORT_CHILDREN:
+ return JcrUtils.nodeIteratorToList(node.getNodes());
+ case EXPORT_GRAND_CHILDREN:
+ NodeIterator nit = node.getNodes();
+ while (nit.hasNext())
+ nodes.addAll(JcrUtils.nodeIteratorToList(nit.nextNode()
+ .getNodes()));
+ return nodes;
+
+ default:
+ return nodes;
+ }
+ }
+
+ // private synchronized void openGeneratedFile(String path, String fileName)
+ // {
+ // Map<String, String> params = new HashMap<String, String>();
+ // params.put(OpenFile.PARAM_FILE_NAME, fileName);
+ // params.put(OpenFile.PARAM_FILE_URI, "file://" + path);
+ // CommandUtils.callCommand("org.argeo.security.ui.specific.openFile",
+ // params);
+ // }
+
+ private class ConfigureDumpWizard extends Wizard {
+
+ // parameters
+ protected String prefix;
+ protected int currExportType = EXPORT_NODE;
+ protected boolean includeBinaries = false;
+
+ // UI Objects
+ private BasicPage page;
+ private Text prefixTxt;
+ private Button includeBinaryBtn;
+ private Button b1, b2, b3;
+
+ public ConfigureDumpWizard(Shell parentShell, String title) {
+ setWindowTitle(title);
+ }
+
+ @Override
+ public void addPages() {
+ try {
+ page = new BasicPage("Main page");
+ addPage(page);
+ } catch (Exception e) {
+ throw new EclipseUiException("Cannot add page to wizard", e);
+ }
+ }
+
+ @Override
+ public boolean performFinish() {
+ prefix = prefixTxt.getText();
+ if (b1.getSelection())
+ currExportType = EXPORT_NODE;
+ else if (b2.getSelection())
+ currExportType = EXPORT_CHILDREN;
+ else if (b3.getSelection())
+ currExportType = EXPORT_GRAND_CHILDREN;
+ includeBinaries = includeBinaryBtn.getSelection();
+ return true;
+ }
+
+ @Override
+ public boolean performCancel() {
+ return true;
+ }
+
+ @Override
+ public boolean canFinish() {
+ String errorMsg = "No prefix defined.";
+ if ("".equals(prefixTxt.getText().trim())) {
+ page.setErrorMessage(errorMsg);
+ return false;
+ } else {
+ page.setErrorMessage(null);
+ return true;
+ }
+ }
+
+ protected class BasicPage extends WizardPage {
+ private static final long serialVersionUID = 1L;
+
+ public BasicPage(String pageName) {
+ super(pageName);
+ setTitle("Configure dump before launching");
+ setMessage("Define the parameters of the dump to launch");
+ }
+
+ public void createControl(Composite parent) {
+ parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
+
+ // Main Layout
+ Composite mainCmp = new Composite(parent, SWT.NONE);
+ mainCmp.setLayout(new GridLayout(2, false));
+ mainCmp.setLayoutData(EclipseUiUtils.fillAll());
+
+ // The path
+ createBoldLabel(mainCmp, "Prefix");
+ prefixTxt = new Text(mainCmp, SWT.SINGLE | SWT.BORDER);
+ prefixTxt.setLayoutData(EclipseUiUtils.fillAll());
+ prefixTxt.addModifyListener(new ModifyListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void modifyText(ModifyEvent event) {
+ if (prefixTxt.getText() != null)
+ getWizard().getContainer().updateButtons();
+ }
+ });
+
+ new Label(mainCmp, SWT.SEPARATOR | SWT.HORIZONTAL)
+ .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+ false, 2, 1));
+
+ // Which node to export
+ Label typeLbl = new Label(mainCmp, SWT.RIGHT);
+ typeLbl.setText(" Type");
+ typeLbl.setFont(EclipseUiUtils.getBoldFont(mainCmp));
+ typeLbl.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false,
+ false, 1, 3));
+
+ b1 = new Button(mainCmp, SWT.RADIO);
+ b1.setText("Export this node");
+ b1.setSelection(true);
+ b2 = new Button(mainCmp, SWT.RADIO);
+ b2.setText("Export children nodes");
+ b3 = new Button(mainCmp, SWT.RADIO);
+ b3.setText("Export grand-children nodes");
+
+ new Label(mainCmp, SWT.SEPARATOR | SWT.HORIZONTAL)
+ .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+ false, 2, 1));
+
+ createBoldLabel(mainCmp, "Files and images");
+ includeBinaryBtn = new Button(mainCmp, SWT.CHECK);
+ includeBinaryBtn.setText("Include binaries");
+
+ prefixTxt.setFocus();
+ setControl(mainCmp);
+ }
+ }
+ }
+
+ private Label createBoldLabel(Composite parent, String value) {
+ Label label = new Label(parent, SWT.RIGHT);
+ label.setText(" " + value);
+ label.setFont(EclipseUiUtils.getBoldFont(parent));
+ label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ return label;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.Arrays;
+
+import org.argeo.cms.ui.jcr.model.RepositoryElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.eclipse.ui.dialogs.SingleValue;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Create a new JCR workspace */
+public class CreateWorkspace extends AbstractHandler {
+
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".addFolderNode";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ if (!(obj instanceof RepositoryElem))
+ return null;
+
+ RepositoryElem repositoryNode = (RepositoryElem) obj;
+ String workspaceName = SingleValue.ask("Workspace name",
+ "Enter workspace name");
+ if (workspaceName != null) {
+ if (Arrays.asList(repositoryNode.getAccessibleWorkspaceNames())
+ .contains(workspaceName)) {
+ ErrorFeedback.show("Workspace " + workspaceName
+ + " already exists.");
+ } else {
+ repositoryNode.createWorkspace(workspaceName);
+ view.nodeAdded(repositoryNode);
+ }
+ }
+ } else {
+ ErrorFeedback.show("Cannot create workspace");
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.Iterator;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * 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 extends AbstractHandler {
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+ if (selection == null || !(selection instanceof IStructuredSelection))
+ return null;
+
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+
+ // confirmation
+ StringBuffer buf = new StringBuffer("");
+ Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+ while (lst.hasNext()) {
+ SingleJcrNodeElem sjn = ((SingleJcrNodeElem) lst.next());
+ buf.append(sjn.getName()).append(' ');
+ }
+ Boolean doRemove = MessageDialog.openConfirm(
+ HandlerUtil.getActiveShell(event), "Confirm deletion",
+ "Do you want to delete " + buf + "?");
+
+ // operation
+ if (doRemove) {
+ Iterator<?> it = ((IStructuredSelection) selection).iterator();
+ Object obj = null;
+ SingleJcrNodeElem ancestor = null;
+ WorkspaceElem rootAncestor = null;
+ try {
+ while (it.hasNext()) {
+ obj = it.next();
+ 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);
+ }
+ }
+ return null;
+ }
+
+ 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import static org.argeo.eclipse.ui.utils.SingleSourcingConstants.FILE_SCHEME;
+import static org.argeo.eclipse.ui.utils.SingleSourcingConstants.SCHEME_HOST_SEPARATOR;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.util.CommandUtils;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.specific.OpenFile;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Canonically call JCR Session#exportSystemView() on the first element returned
+ * by HandlerUtil#getActiveWorkbenchWindow()
+ * (...getActivePage().getSelection()), if it is a {@link SingleJcrNodeElem},
+ * with both skipBinary and noRecurse boolean flags set to false.
+ *
+ * Resulting stream is saved in a tmp file and opened via the {@link OpenFile}
+ * single-sourced command.
+ */
+public class DumpNode extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".dumpNode";
+
+ private final static DateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH-mm");
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection();
+ if (selection == null || !(selection instanceof IStructuredSelection))
+ return null;
+
+ Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+ if (lst.hasNext()) {
+ Object element = lst.next();
+ if (element instanceof SingleJcrNodeElem) {
+ SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
+ Node node = sjn.getNode();
+
+ // TODO add a dialog to configure the export and ask for
+ // confirmation
+ // Boolean ok = MessageDialog.openConfirm(
+ // HandlerUtil.getActiveShell(event), "Confirm dump",
+ // "Do you want to dump " + buf + "?");
+
+ File tmpFile;
+ FileOutputStream fos;
+ try {
+ tmpFile = File.createTempFile("JcrExport", ".xml");
+ tmpFile.deleteOnExit();
+ fos = new FileOutputStream(tmpFile);
+ String dateVal = df.format(new GregorianCalendar().getTime());
+ node.getSession().exportSystemView(node.getPath(), fos, true, false);
+ openGeneratedFile(tmpFile.getAbsolutePath(),
+ "Dump-" + JcrUtils.replaceInvalidChars(node.getName()) + "-" + dateVal + ".xml");
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to perform SystemExport on " + node, e);
+ } catch (IOException e) {
+ throw new EclipseUiException("Unable to SystemExport " + node, e);
+ }
+ }
+ }
+ return null;
+ }
+
+ private synchronized void openGeneratedFile(String path, String fileName) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(OpenFile.PARAM_FILE_NAME, fileName);
+ params.put(OpenFile.PARAM_FILE_URI, FILE_SCHEME + SCHEME_HOST_SEPARATOR + path);
+ CommandUtils.callCommand(OpenFile.ID, params);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.cms.ui.workbench.internal.jcr.parts.NodeEditorInput;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Generic command to open a Node in an editor. */
+public class EditNode extends AbstractHandler {
+ public final static String PARAM_EDITOR_ID = "editor";
+
+ private String defaultEditorId;
+
+ private Map<String, String> nodeTypeToEditor = new HashMap<String, String>();
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String path = event.getParameter(Property.JCR_PATH);
+ String type = event.getParameter(NodeType.NT_NODE_TYPE);
+ if (type == null)
+ type = NodeType.NT_UNSTRUCTURED;
+
+ String editorId = event.getParameter(PARAM_EDITOR_ID);
+ if (editorId == null)
+ editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor
+ .get(type) : defaultEditorId;
+
+ NodeEditorInput nei = new NodeEditorInput(path);
+ try {
+ HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+ .openEditor(nei, editorId);
+ } catch (PartInitException e) {
+ ErrorFeedback.show("Cannot open " + editorId + " with " + path
+ + " of type " + type, e);
+ }
+ return null;
+ }
+
+ public void setDefaultEditorId(String defaultEditorId) {
+ this.defaultEditorId = defaultEditorId;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Compute an approximative size for the selected node(s) */
+public class GetNodeSize extends AbstractHandler {
+ // private final static Log log = LogFactory.getLog(GetNodeSize.class);
+
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".getNodeSize";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+
+ long size = 0;
+
+ Iterator<?> it = ((IStructuredSelection) selection).iterator();
+
+ // TODO enhance this: as the size method is recursive, we keep track
+ // of nodes for which we already have computed size so that we don't
+ // count them twice. In a first approximation, we assume that the
+ // structure selection keep the nodes ordered.
+ List<String> importedPathes = new ArrayList<String>();
+ try {
+ nodesIt: while (it.hasNext()) {
+ Object obj = it.next();
+ String curPath;
+ Node node;
+ if (obj instanceof SingleJcrNodeElem) {
+ node = ((SingleJcrNodeElem) obj).getNode();
+ curPath = node.getSession().getWorkspace().getName();
+ curPath += "/" + node.getPath();
+ } else if (obj instanceof WorkspaceElem) {
+ node = ((WorkspaceElem) obj).getRootNode();
+ curPath = node.getSession().getWorkspace().getName();
+ } else
+ // non valid object type
+ continue nodesIt;
+
+ Iterator<String> itPath = importedPathes.iterator();
+ while (itPath.hasNext()) {
+ String refPath = itPath.next();
+ if (curPath.startsWith(refPath))
+ // Already done : skip node
+ continue nodesIt;
+ }
+ size += JcrUtils.getNodeApproxSize(node);
+ importedPathes.add(curPath);
+ }
+ } catch (Exception e) {
+ ErrorFeedback.show("Cannot Get size of selected node ", e);
+ }
+
+ String[] labels = { "OK" };
+ Shell shell = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getShell();
+ MessageDialog md = new MessageDialog(shell, "Node size", null,
+ "Node size is: " + size / 1024 + " KB",
+ MessageDialog.INFORMATION, labels, 0);
+ md.open();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.Iterator;
+
+import org.argeo.cms.ui.jcr.JcrBrowserUtils;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.TreeParent;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * Force the selected objects of the active view to be refreshed doing the
+ * following:
+ * <ol>
+ * <li>The model objects are recomputed</li>
+ * <li>the view is refreshed</li>
+ * </ol>
+ */
+public class Refresh extends AbstractHandler {
+
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".refresh";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ JcrBrowserView view = (JcrBrowserView) WorkbenchUiPlugin.getDefault()
+ .getWorkbench().getActiveWorkbenchWindow().getActivePage()
+ .getActivePart();//
+
+ ISelection selection = WorkbenchUiPlugin.getDefault().getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage().getSelection();
+
+ if (selection != null && selection instanceof IStructuredSelection
+ && !selection.isEmpty()) {
+ Iterator<?> it = ((IStructuredSelection) selection).iterator();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof TreeParent) {
+ TreeParent tp = (TreeParent) obj;
+ JcrBrowserUtils.forceRefreshIfNeeded(tp);
+ view.refresh(obj);
+ }
+ }
+ } else if (view instanceof JcrBrowserView)
+ ((JcrBrowserView) view).refresh(null); // force full refresh
+
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.security.Principal;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import org.argeo.cms.ui.jcr.JcrImages;
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+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.jface.viewers.ISelection;
+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.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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Open a dialog to remove privileges from the selected node */
+public class RemovePrivileges extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".removePrivileges";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ TreeParent uiNode = null;
+ Node jcrNode = null;
+
+ if (obj instanceof SingleJcrNodeElem) {
+ uiNode = (TreeParent) obj;
+ jcrNode = ((SingleJcrNodeElem) uiNode).getNode();
+ } else if (obj instanceof WorkspaceElem) {
+ uiNode = (TreeParent) obj;
+ jcrNode = ((WorkspaceElem) uiNode).getRootNode();
+ } else
+ return null;
+
+ try {
+ String targetPath = jcrNode.getPath();
+ Dialog dialog = new RemovePrivDialog(
+ HandlerUtil.getActiveShell(event),
+ jcrNode.getSession(), targetPath);
+ dialog.open();
+ return null;
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Unable to retrieve "
+ + "path or JCR session to add privilege on " + jcrNode,
+ re);
+ }
+ } else {
+ ErrorFeedback.show("Cannot add privileges");
+ }
+ return null;
+ }
+
+ private class RemovePrivDialog extends TitleAreaDialog {
+ private static final long serialVersionUID = 280139710002698692L;
+
+ private Composite body;
+
+ private final String path;
+ private final Session session;
+
+ public RemovePrivDialog(Shell parentShell, Session session, String path) {
+ super(parentShell);
+ this.session = session;
+ this.path = path;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText("Remove privileges");
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogarea = (Composite) super.createDialogArea(parent);
+ dialogarea.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true,
+ true));
+ body = new Composite(dialogarea, SWT.NONE);
+ body.setLayoutData(EclipseUiUtils.fillAll());
+ refreshContent();
+ parent.pack();
+ return body;
+ }
+
+ private void refreshContent() {
+ EclipseUiUtils.clear(body);
+ try {
+ AccessControlManager acm = session.getAccessControlManager();
+ AccessControlList acl = JcrUtils
+ .getAccessControlList(acm, path);
+ if (acl == null || acl.getAccessControlEntries().length <= 0)
+ setMessage("No privilege are defined on this node",
+ IMessageProvider.INFORMATION);
+ else {
+ body.setLayout(new GridLayout(3, false));
+ for (AccessControlEntry ace : acl.getAccessControlEntries()) {
+ addOnePrivRow(body, ace);
+ }
+ setMessage("Remove some of the defined privileges",
+ IMessageProvider.INFORMATION);
+ }
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to list privileges on "
+ + path, e);
+ }
+ body.layout(true, true);
+ }
+
+ private void addOnePrivRow(Composite parent, AccessControlEntry ace) {
+ Principal currentPrincipal = ace.getPrincipal();
+ final String currPrincipalName = currentPrincipal.getName();
+ new Label(parent, SWT.WRAP).setText(currPrincipalName);
+ new Label(parent, SWT.WRAP).setText(privAsString(ace
+ .getPrivileges()));
+ final Button rmBtn = new Button(parent, SWT.FLAT);
+ rmBtn.setImage(JcrImages.REMOVE);
+
+ rmBtn.addSelectionListener(new SelectionAdapter() {
+ private static final long serialVersionUID = 7566938841363890730L;
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+
+ if (MessageDialog.openConfirm(rmBtn.getShell(),
+ "Confirm deletion",
+ "Are you sure you want to remove this privilege?")) {
+ try {
+ session.save();
+ JcrUtils.clearAccessControList(session, path,
+ currPrincipalName);
+ session.save();
+ refreshContent();
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Unable to "
+ + "remove privilege for "
+ + currPrincipalName + " on " + path, re);
+ }
+ }
+
+ super.widgetSelected(e);
+ }
+ });
+
+ }
+
+ private String privAsString(Privilege[] currentPrivileges) {
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("[ ");
+ for (Privilege priv : currentPrivileges) {
+ builder.append(priv.getName()).append(", ");
+ }
+ if (builder.length() > 3)
+ return builder.substring(0, builder.length() - 2) + " ]";
+ else
+ return "[]";
+
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import org.argeo.cms.ui.jcr.model.RemoteRepositoryElem;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Remove a registered remote repository */
+public class RemoveRemoteRepository extends AbstractHandler {
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getSelection();
+
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+
+ if (selection != null && !selection.isEmpty()
+ && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+
+ if (obj instanceof RemoteRepositoryElem) {
+ ((RemoteRepositoryElem) obj).remove();
+ view.refresh(null);
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import java.util.Iterator;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.dialogs.SingleValue;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * 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 extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".renameNode";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ IWorkbenchPage iwp = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
+
+ ISelection selection = iwp.getSelection();
+ if (selection == null || !(selection instanceof IStructuredSelection))
+ return null;
+
+ Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+ if (lst.hasNext()) {
+ Object element = lst.next();
+ 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
+ if (iwp.getActivePart() instanceof JcrBrowserView)
+ ((JcrBrowserView) iwp.getActivePart()).refresh(sjn);
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to rename " + node + " to " + newName, e);
+ }
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.State;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Change isSorted state of the DataExplorer Browser */
+public class SortChildNodes extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".sortChildNodes";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil
+ .getActiveWorkbenchWindow(event).getActivePage()
+ .findView(JcrBrowserView.ID);
+
+ ICommandService service = (ICommandService) PlatformUI.getWorkbench()
+ .getService(ICommandService.class);
+ Command command = service.getCommand(ID);
+ State state = command.getState(ID + ".toggleState");
+
+ boolean wasSorted = (Boolean) state.getValue();
+ view.setSortChildNodes(!wasSorted);
+ state.setValue(!wasSorted);
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.commands;
+
+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 javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.jcr.model.WorkspaceElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.JcrBrowserView;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Upload local file(s) under the currently selected node */
+public class UploadFiles extends AbstractHandler {
+ // private final static Log log = LogFactory.getLog(ImportFileSystem.class);
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection();
+ JcrBrowserView view = (JcrBrowserView) HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+ .findView(HandlerUtil.getActivePartId(event));
+ if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) {
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+ try {
+ Node folder = null;
+ if (obj instanceof SingleJcrNodeElem) {
+ folder = ((SingleJcrNodeElem) obj).getNode();
+ } else if (obj instanceof WorkspaceElem) {
+ folder = ((WorkspaceElem) obj).getRootNode();
+ } else {
+ ErrorFeedback.show(WorkbenchUiPlugin.getMessage("warningInvalidNodeToImport"));
+ }
+ if (folder != null) {
+ FileDialog dialog = new FileDialog(HandlerUtil.getActiveShell(event), 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 null;
+ else {
+ loop: for (String name : names) {
+ Path path = Paths.get(name);
+ if (parPath != null)
+ path = parPath.resolve(path);
+ if (Files.exists(path)) {
+ URI uri = path.toUri();
+ String uriStr = uri.toString();
+ System.out.println(uriStr);
+
+ if (Files.isDirectory(path)) {
+ MessageDialog.openError(HandlerUtil.getActiveShell(event),
+ "Unimplemented directory import",
+ "Upload of directories in the system is not yet implemented");
+ continue loop;
+ }
+ Node fileNode = folder.addNode(path.getFileName().toString(), NodeType.NT_FILE);
+ Node resNode = fileNode.addNode(Property.JCR_CONTENT, NodeType.NT_RESOURCE);
+ Binary binary = null;
+ try (InputStream is = Files.newInputStream(path)) {
+ binary = folder.getSession().getValueFactory().createBinary(is);
+ resNode.setProperty(Property.JCR_DATA, binary);
+ }
+ folder.getSession().save();
+ } else {
+ String msg = "Cannot upload file at " + path.toString();
+ if (parPath != null)
+ msg += "\nPlease remember that file upload fails when choosing files from the \"Recently Used\" bookmarks on some OS";
+ MessageDialog.openError(HandlerUtil.getActiveShell(event), "Missing file", msg);
+ continue loop;
+ }
+ }
+ view.nodeAdded((TreeParent) obj);
+ return true;
+ }
+ }
+ }
+ } catch (Exception e) {
+ ErrorFeedback.show("Cannot import files to " + obj, e);
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.Row;
+import javax.jcr.query.RowIterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.GenericTableComparator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.TableColumn;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorPart;
+
+/** Executes any JCR query. */
+public abstract class AbstractJcrQueryEditor extends EditorPart {
+ private final static Log log = LogFactory.getLog(AbstractJcrQueryEditor.class);
+
+ protected String initialQuery;
+ protected String initialQueryType;
+
+ /* DEPENDENCY INJECTION */
+ private Session session;
+
+ // Widgets
+ private TableViewer viewer;
+ private List<TableViewerColumn> tableViewerColumns = new ArrayList<TableViewerColumn>();
+ private GenericTableComparator comparator;
+
+ /** Override to layout a form enabling the end user to build his query */
+ protected abstract void createQueryForm(Composite parent);
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ JcrQueryEditorInput editorInput = (JcrQueryEditorInput) input;
+ initialQuery = editorInput.getQuery();
+ initialQueryType = editorInput.getQueryType();
+ setSite(site);
+ setInput(editorInput);
+ }
+
+ @Override
+ public final void createPartControl(final Composite parent) {
+ parent.setLayout(new FillLayout());
+
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
+ sashForm.setSashWidth(4);
+ sashForm.setLayout(new FillLayout());
+
+ Composite top = new Composite(sashForm, SWT.NONE);
+ GridLayout gl = new GridLayout(1, false);
+ top.setLayout(gl);
+
+ createQueryForm(top);
+
+ Composite bottom = new Composite(sashForm, SWT.NONE);
+ bottom.setLayout(new GridLayout(1, false));
+ sashForm.setWeights(getWeights());
+
+ viewer = new TableViewer(bottom);
+ viewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ viewer.getTable().setHeaderVisible(true);
+ viewer.setContentProvider(getQueryResultContentProvider());
+ viewer.setInput(getEditorSite());
+
+ if (getComparator() != null) {
+ comparator = getComparator();
+ viewer.setComparator(comparator);
+ }
+ if (getTableDoubleClickListener() != null)
+ viewer.addDoubleClickListener(getTableDoubleClickListener());
+
+ }
+
+ protected void executeQuery(String statement) {
+ try {
+ if (log.isDebugEnabled())
+ log.debug("Query : " + statement);
+
+ QueryResult qr = session.getWorkspace().getQueryManager().createQuery(statement, initialQueryType)
+ .execute();
+
+ // remove previous columns
+ for (TableViewerColumn tvc : tableViewerColumns)
+ tvc.getColumn().dispose();
+
+ int i = 0;
+ for (final String columnName : qr.getColumnNames()) {
+ TableViewerColumn tvc = new TableViewerColumn(viewer, SWT.NONE);
+ configureColumn(columnName, tvc, i);
+ tvc.setLabelProvider(getLabelProvider(columnName));
+ tableViewerColumns.add(tvc);
+ i++;
+ }
+
+ // Must create a local list: QueryResults can only be read once.
+ try {
+ List<Row> rows = new ArrayList<Row>();
+ RowIterator rit = qr.getRows();
+ while (rit.hasNext()) {
+ rows.add(rit.nextRow());
+ }
+ viewer.setInput(rows);
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot read query result", e);
+ }
+
+ } catch (RepositoryException e) {
+ ErrorDialog.openError(null, "Error", "Cannot execute JCR query: " + statement,
+ new Status(IStatus.ERROR, "org.argeo.eclipse.ui.jcr", e.getMessage()));
+ }
+ }
+
+ /**
+ * To be overidden to adapt size of form and result frames.
+ *
+ * @return
+ */
+ protected int[] getWeights() {
+ return new int[] { 30, 70 };
+ }
+
+ /**
+ * To be overidden to implement a doubleclick Listener on one of the rows of
+ * the table.
+ *
+ * @return
+ */
+ protected IDoubleClickListener getTableDoubleClickListener() {
+ return null;
+ }
+
+ /**
+ * To be overiden in order to implement a specific
+ * QueryResultContentProvider
+ */
+ protected IStructuredContentProvider getQueryResultContentProvider() {
+ return new QueryResultContentProvider();
+ }
+
+ /**
+ * Enable specific implementation for columns
+ */
+ protected List<TableViewerColumn> getTableViewerColumns() {
+ return tableViewerColumns;
+ }
+
+ /**
+ * Enable specific implementation for columns
+ */
+ protected TableViewer getTableViewer() {
+ return viewer;
+ }
+
+ /**
+ * To be overridden in order to configure column label providers .
+ */
+ protected ColumnLabelProvider getLabelProvider(final String columnName) {
+ return new ColumnLabelProvider() {
+ private static final long serialVersionUID = -3539689333250152606L;
+
+ public String getText(Object element) {
+ Row row = (Row) element;
+ try {
+ return row.getValue(columnName).getString();
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot display row " + row, e);
+ }
+ }
+
+ public Image getImage(Object element) {
+ return null;
+ }
+ };
+ }
+
+ /**
+ * To be overridden in order to configure the columns.
+ *
+ * @deprecated use
+ * {@link AbstractJcrQueryEditor#configureColumn(String, TableViewerColumn , int )}
+ * instead
+ */
+ protected void configureColumn(String jcrColumnName, TableViewerColumn column) {
+ column.getColumn().setWidth(50);
+ column.getColumn().setText(jcrColumnName);
+ }
+
+ /** To be overridden in order to configure the columns. */
+ protected void configureColumn(String jcrColumnName, TableViewerColumn column, int columnIndex) {
+ column.getColumn().setWidth(50);
+ column.getColumn().setText(jcrColumnName);
+ }
+
+ private class QueryResultContentProvider implements IStructuredContentProvider {
+ private static final long serialVersionUID = -5421095459600554741L;
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public Object[] getElements(Object inputElement) {
+
+ if (inputElement instanceof List)
+ return ((List<?>) inputElement).toArray();
+
+ // Never reached might be deleted in future release
+ if (!(inputElement instanceof QueryResult))
+ return new String[] {};
+
+ try {
+ QueryResult queryResult = (QueryResult) inputElement;
+ List<Row> rows = new ArrayList<Row>();
+ RowIterator rit = queryResult.getRows();
+ while (rit.hasNext()) {
+ rows.add(rit.nextRow());
+ }
+
+ // List<Node> elems = new ArrayList<Node>();
+ // NodeIterator nit = queryResult.getNodes();
+ // while (nit.hasNext()) {
+ // elems.add(nit.nextNode());
+ // }
+ return rows.toArray();
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot read query result", e);
+ }
+ }
+
+ }
+
+ /**
+ * Might be used by children classes to sort columns.
+ *
+ * @param column
+ * @param index
+ * @return
+ */
+ protected SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) {
+
+ // A comparator must be define
+ if (comparator == null)
+ return null;
+
+ SelectionAdapter selectionAdapter = new SelectionAdapter() {
+ private static final long serialVersionUID = 239829307927778349L;
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+
+ try {
+
+ comparator.setColumn(index);
+ int dir = viewer.getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column) {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ } else {
+
+ dir = SWT.DOWN;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ }
+ };
+ return selectionAdapter;
+ }
+
+ /**
+ * To be overridden to enable sorting.
+ */
+ protected GenericTableComparator getComparator() {
+ return null;
+ }
+
+ @Override
+ public boolean isDirty() {
+ return false;
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor) {
+ // TODO save the query in JCR?
+ }
+
+ @Override
+ public void doSaveAs() {
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ /** Returns the injected current session */
+ protected Session getSession() {
+ return session;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setSession(Session session) {
+ this.session = session;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+
+import org.argeo.cms.ui.useradmin.PickUpUserDialog;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.Wizard;
+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.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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/** Add JCR privileges to the chosen user group on a given node */
+public class AddPrivilegeWizard extends Wizard {
+
+ // Context
+ private UserAdmin userAdmin;
+ private Session currentSession;
+ private String targetPath;
+ // Chosen parameters
+ private String chosenDn;
+ private User chosenUser;
+ private String jcrPrivilege;
+
+ // UI Object
+ private DefinePrivilegePage page;
+
+ // TODO enable external definition of possible values and corresponding
+ // description
+ protected static final Map<String, String> AUTH_TYPE_LABELS;
+ static {
+ Map<String, String> tmpMap = new HashMap<String, String>();
+ tmpMap.put(Privilege.JCR_READ, "jcr:read");
+ tmpMap.put(Privilege.JCR_WRITE, "jcr:write");
+ tmpMap.put(Privilege.JCR_ALL, "jcr:all");
+ AUTH_TYPE_LABELS = Collections.unmodifiableMap(tmpMap);
+ }
+
+ protected static final Map<String, String> AUTH_TYPE_DESC;
+ static {
+ Map<String, String> tmpMap = new HashMap<String, String>();
+ tmpMap.put(Privilege.JCR_READ, "The privilege to retrieve a node and get its properties and their values.");
+ tmpMap.put(Privilege.JCR_WRITE, "An aggregate privilege that "
+ + "contains: jcr:modifyProperties, jcr:addChildNodes, " + "jcr:removeNode, jcr:removeChildNodes");
+ tmpMap.put(Privilege.JCR_ALL, "An aggregate privilege that " + "contains all JCR predefined privileges, "
+ + "plus all implementation-defined privileges. ");
+ AUTH_TYPE_DESC = Collections.unmodifiableMap(tmpMap);
+ }
+
+ public AddPrivilegeWizard(Session currentSession, String path, UserAdmin userAdmin) {
+ super();
+ this.userAdmin = userAdmin;
+ this.currentSession = currentSession;
+ this.targetPath = path;
+ }
+
+ @Override
+ public void addPages() {
+ try {
+ setWindowTitle("Add privilege on " + targetPath);
+ page = new DefinePrivilegePage(userAdmin, targetPath);
+ addPage(page);
+ } catch (Exception e) {
+ throw new EclipseUiException("Cannot add page to wizard ", e);
+ }
+ }
+
+ @Override
+ public boolean performFinish() {
+ if (!canFinish())
+ return false;
+ try {
+ String username = chosenUser.getName();
+ if (EclipseUiUtils.notEmpty(chosenDn) && chosenDn.equalsIgnoreCase(username))
+ // Enable forcing the username case. TODO clean once this issue
+ // has been generally addressed
+ username = chosenDn;
+ JcrUtils.addPrivilege(currentSession, targetPath, username, jcrPrivilege);
+ } catch (RepositoryException re) {
+ throw new EclipseUiException(
+ "Cannot set " + jcrPrivilege + " for " + chosenUser.getName() + " on " + targetPath, re);
+ }
+ return true;
+ }
+
+ private class DefinePrivilegePage extends WizardPage implements ModifyListener {
+ private static final long serialVersionUID = 8084431378762283920L;
+
+ // Context
+ final private UserAdmin userAdmin;
+
+ public DefinePrivilegePage(UserAdmin userAdmin, String path) {
+ super("Main");
+ this.userAdmin = userAdmin;
+ setTitle("Define the privilege to apply to " + path);
+ setMessage("Please choose a user or a group and relevant JCR Privilege.");
+ }
+
+ public void createControl(Composite parent) {
+ final Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+
+ // specify subject
+ createBoldLabel(composite, "User or group name");
+ final Label userNameLbl = new Label(composite, SWT.LEAD);
+ userNameLbl.setLayoutData(EclipseUiUtils.fillWidth());
+
+ Link pickUpLk = new Link(composite, SWT.LEFT);
+ pickUpLk.setText(" <a>Change</a> ");
+
+ createBoldLabel(composite, "User or group DN");
+ final Text userNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER);
+ userNameTxt.setLayoutData(EclipseUiUtils.fillWidth(2));
+
+ pickUpLk.addSelectionListener(new SelectionAdapter() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ PickUpUserDialog dialog = new PickUpUserDialog(getShell(), "Choose a group or a user", userAdmin);
+ if (dialog.open() == Window.OK) {
+ chosenUser = dialog.getSelected();
+ userNameLbl.setText(UserAdminUtils.getCommonName(chosenUser));
+ userNameTxt.setText(chosenUser.getName());
+ }
+ }
+ });
+
+ userNameTxt.addFocusListener(new FocusListener() {
+ private static final long serialVersionUID = 1965498600105667738L;
+
+ @Override
+ public void focusLost(FocusEvent event) {
+ String dn = userNameTxt.getText();
+ if (EclipseUiUtils.isEmpty(dn))
+ return;
+
+ User newChosen = null;
+ try {
+ newChosen = (User) userAdmin.getRole(dn);
+ } catch (Exception e) {
+ boolean tryAgain = MessageDialog.openQuestion(getShell(), "Unvalid DN",
+ "DN " + dn + " is not valid.\nError message: " + e.getMessage()
+ + "\n\t\tDo you want to try again?");
+ if (tryAgain)
+ userNameTxt.setFocus();
+ else
+ resetOnFail();
+ }
+
+ if (userAdmin.getRole(dn) == null) {
+ boolean tryAgain = MessageDialog.openQuestion(getShell(), "Unexisting role",
+ "User/group " + dn + " does not exist. " + "Do you want to try again?");
+ if (tryAgain)
+ userNameTxt.setFocus();
+ else
+ resetOnFail();
+ } else {
+ chosenUser = newChosen;
+ chosenDn = dn;
+ userNameLbl.setText(UserAdminUtils.getCommonName(chosenUser));
+ }
+ }
+
+ private void resetOnFail() {
+ String oldDn = chosenUser == null ? "" : chosenUser.getName();
+ userNameTxt.setText(oldDn);
+ }
+
+ @Override
+ public void focusGained(FocusEvent event) {
+ }
+ });
+
+ // JCR Privileges
+ createBoldLabel(composite, "Privilege type");
+ Combo authorizationCmb = new Combo(composite, SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL);
+ authorizationCmb.setItems(AUTH_TYPE_LABELS.values().toArray(new String[0]));
+ authorizationCmb.setLayoutData(EclipseUiUtils.fillWidth(2));
+ createBoldLabel(composite, ""); // empty cell
+ final Label descLbl = new Label(composite, SWT.WRAP);
+ descLbl.setLayoutData(EclipseUiUtils.fillWidth(2));
+
+ authorizationCmb.addSelectionListener(new SelectionAdapter() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ String chosenPrivStr = ((Combo) e.getSource()).getText();
+ if (AUTH_TYPE_LABELS.containsValue(chosenPrivStr)) {
+ loop: for (String key : AUTH_TYPE_LABELS.keySet()) {
+ if (AUTH_TYPE_LABELS.get(key).equals(chosenPrivStr)) {
+ jcrPrivilege = key;
+ break loop;
+ }
+ }
+ }
+
+ if (jcrPrivilege != null) {
+ descLbl.setText(AUTH_TYPE_DESC.get(jcrPrivilege));
+ composite.layout(true, true);
+ }
+ }
+ });
+
+ // Compulsory
+ setControl(composite);
+ }
+
+ public void modifyText(ModifyEvent event) {
+ String message = checkComplete();
+ if (message != null)
+ setMessage(message, WizardPage.ERROR);
+ else {
+ setMessage("Complete", WizardPage.INFORMATION);
+ setPageComplete(true);
+ }
+ }
+
+ /** @return error message or null if complete */
+ protected String checkComplete() {
+ if (chosenUser == null)
+ return "Please choose a relevant group or user";
+ else if (userAdmin.getRole(chosenUser.getName()) == null)
+ return "Please choose a relevant group or user";
+ else if (jcrPrivilege == null)
+ return "Please choose a relevant JCR privilege";
+ return null;
+ }
+ }
+
+ private Label createBoldLabel(Composite parent, String value) {
+ Label label = new Label(parent, SWT.RIGHT);
+ label.setText(" " + value);
+ label.setFont(EclipseUiUtils.getBoldFont(parent));
+ label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ return label;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import javax.jcr.Node;
+
+import org.argeo.cms.ui.jcr.JcrTreeContentProvider;
+import org.argeo.cms.ui.jcr.NodeLabelProvider;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.jcr.DefaultNodeEditor;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/** List all children of the current node */
+public class ChildNodesPage extends FormPage {
+ // private final static Log log = LogFactory.getLog(ChildNodesPage.class);
+
+ private Node currentNode;
+
+ private JcrTreeContentProvider nodeContentProvider;
+ private TreeViewer nodesViewer;
+
+ public ChildNodesPage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "ChildNodesPage", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ try {
+ ScrolledForm form = managedForm.getForm();
+ form.setText(WorkbenchUiPlugin.getMessage("childNodesPageTitle"));
+ Composite innerBox = form.getBody();
+ // Composite innerBox = new Composite(body, SWT.NO_FOCUS);
+ GridLayout twt = new GridLayout(1, false);
+ twt.marginWidth = twt.marginHeight = 5;
+ innerBox.setLayout(twt);
+ if (!currentNode.hasNodes()) {
+ managedForm.getToolkit().createLabel(innerBox, WorkbenchUiPlugin.getMessage("warningNoChildNode"));
+ } else {
+ nodeContentProvider = new JcrTreeContentProvider();
+ nodesViewer = createNodeViewer(innerBox, nodeContentProvider);
+ nodesViewer.setInput(currentNode);
+ }
+ } catch (Exception e) {
+ throw new EclipseUiException("Cannot create children page for " + currentNode, e);
+ }
+ }
+
+ protected TreeViewer createNodeViewer(Composite parent, final ITreeContentProvider nodeContentProvider) {
+
+ final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.BORDER);
+ Tree tree = tmpNodeViewer.getTree();
+ tree.setLinesVisible(true);
+ tmpNodeViewer.getTree().setLayoutData(EclipseUiUtils.fillAll());
+ tmpNodeViewer.setContentProvider(nodeContentProvider);
+ tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
+ tmpNodeViewer.addDoubleClickListener(new DClickListener());
+ return tmpNodeViewer;
+ }
+
+ public class DClickListener implements IDoubleClickListener {
+
+ public void doubleClick(DoubleClickEvent event) {
+ if (event.getSelection() == null || event.getSelection().isEmpty())
+ return;
+ Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement();
+ if (obj instanceof Node) {
+ Node node = (Node) obj;
+ try {
+ GenericNodeEditorInput gnei = new GenericNodeEditorInput(node);
+ WorkbenchUiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage()
+ .openEditor(gnei, DefaultNodeEditor.ID);
+ } catch (PartInitException pie) {
+ throw new EclipseUiException("Cannot open editor for " + node, pie);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** Ask end user for a name */
+public class ChooseNameDialog extends TitleAreaDialog {
+ private static final long serialVersionUID = 280139710002698692L;
+ private Text nameTxt;
+
+ public ChooseNameDialog(Shell parentShell) {
+ super(parentShell);
+ setTitle("Choose name");
+ }
+
+ protected Point getInitialSize() {
+ return new Point(300, 250);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogarea = (Composite) super.createDialogArea(parent);
+ dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ Composite composite = new Composite(dialogarea, SWT.NONE);
+ composite.setLayout(new GridLayout(2, false));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ nameTxt = createLT(composite, "Name");
+ setMessage("Choose name", IMessageProvider.INFORMATION);
+ parent.pack();
+ nameTxt.setFocus();
+ return composite;
+ }
+
+ /** Creates label and text. */
+ protected Text createLT(Composite parent, String label) {
+ new Label(parent, SWT.NONE).setText(label);
+ Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ return text;
+ }
+
+ public String getName() {
+ return nameTxt.getText();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/** Editor input for {@link Node} editors */
+public class GenericNodeEditorInput implements IEditorInput {
+ private final Node currentNode;
+
+ // Caches key properties at creation time to avoid Exception at recovering
+ // time when the session has been closed
+ private String path;
+ private String uid;
+ private String name;
+
+ public GenericNodeEditorInput(Node currentNode) {
+ this.currentNode = currentNode;
+ try {
+ name = currentNode.getName();
+ uid = currentNode.getIdentifier();
+ path = currentNode.getPath();
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Cannot cache the key properties for " + currentNode, re);
+ }
+ }
+
+ public Node getCurrentNode() {
+ return currentNode;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getUid() {
+ return uid;
+ }
+
+ public String getToolTipText() {
+ return path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ /**
+ * Equals method based on UID that is unique within a workspace and path of
+ * the node, thus 2 shared node that have same UID as defined in the spec
+ * but 2 different paths will open two distinct editors.
+ *
+ * TODO enhance this method to support multi repository and multi workspace
+ * environments
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+
+ GenericNodeEditorInput other = (GenericNodeEditorInput) obj;
+ if (!getUid().equals(other.getUid()))
+ return false;
+ if (!getPath().equals(other.getPath()))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.CmsConstants;
+import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.jcr.JcrUtils;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * Work-In-Progress Node editor page: provides edition feature on String
+ * properties for power users. TODO implement manual modification of all
+ * property types.
+ */
+
+public class GenericNodePage extends FormPage implements WorkbenchConstants {
+ // private final static Log log = LogFactory.getLog(GenericNodePage.class);
+
+ // local constants
+ private final static String JCR_PROPERTY_NAME = "jcr:name";
+
+ // Utils
+ protected DateFormat timeFormatter = new SimpleDateFormat(CmsConstants.DATE_TIME_FORMAT);
+
+ // Main business Objects
+ private Node currentNode;
+
+ // This page widgets
+ private FormToolkit tk;
+ private List<Control> modifyableProperties = new ArrayList<Control>();
+
+ public GenericNodePage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "id", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ tk = managedForm.getToolkit();
+ ScrolledForm form = managedForm.getForm();
+ Composite innerBox = form.getBody();
+ // Composite innerBox = new Composite(form.getBody(), SWT.NO_FOCUS);
+ GridLayout twt = new GridLayout(3, false);
+ innerBox.setLayout(twt);
+ createPropertiesPart(innerBox);
+ }
+
+ private void createPropertiesPart(Composite parent) {
+ try {
+ AbstractFormPart part = new AbstractFormPart() {
+ public void commit(boolean onSave) {
+ try {
+ if (onSave) {
+ ListIterator<Control> it = modifyableProperties.listIterator();
+ while (it.hasNext()) {
+ // we only support Text controls
+ Text curControl = (Text) it.next();
+ String value = curControl.getText();
+ currentNode.setProperty((String) curControl.getData(JCR_PROPERTY_NAME), value);
+ }
+
+ // We only commit when onSave = true,
+ // thus it is still possible to save after a tab
+ // change.
+ if (currentNode.getSession().hasPendingChanges())
+ currentNode.getSession().save();
+ super.commit(onSave);
+ }
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Cannot save properties on " + currentNode, re);
+ }
+ }
+ };
+
+ PropertyIterator pi = currentNode.getProperties();
+ while (pi.hasNext()) {
+ Property prop = pi.nextProperty();
+ addPropertyLine(parent, part, prop);
+ }
+ getManagedForm().addPart(part);
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Cannot display properties for " + currentNode, re);
+ }
+ }
+
+ private void addPropertyLine(Composite parent, AbstractFormPart part, Property prop) {
+ try {
+ tk.createLabel(parent, prop.getName());
+ tk.createLabel(parent, "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
+
+ if (prop.getDefinition().isProtected()) {
+ tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+ } else
+ addModifyableValueWidget(parent, part, prop);
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Cannot display property " + prop, re);
+ }
+ }
+
+ private String formatReadOnlyPropertyValue(Property prop) throws RepositoryException {
+ String strValue;
+ if (prop.getType() == PropertyType.BINARY)
+ strValue = "<binary>";
+ else if (prop.isMultiple())
+ strValue = Arrays.asList(prop.getValues()).toString();
+ else if (prop.getType() == PropertyType.DATE)
+ strValue = timeFormatter.format(prop.getValue().getDate().getTime());
+ else
+ strValue = prop.getValue().getString();
+ return strValue;
+ }
+
+ private Control addModifyableValueWidget(Composite parent, AbstractFormPart part, Property prop)
+ throws RepositoryException {
+ GridData gd;
+ if (prop.getType() == PropertyType.STRING && !prop.isMultiple()) {
+ Text txt = tk.createText(parent, prop.getString(), SWT.WRAP | SWT.MULTI);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ txt.setLayoutData(gd);
+ txt.addModifyListener(new ModifiedFieldListener(part));
+ txt.setData(JCR_PROPERTY_NAME, prop.getName());
+ modifyableProperties.add(txt);
+ } else {
+ // unsupported property type for editing, we create a read only
+ // label.
+ return tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+ }
+ return null;
+ }
+
+ private class ModifiedFieldListener implements ModifyListener {
+ private static final long serialVersionUID = 2117484480773434646L;
+ private AbstractFormPart formPart;
+
+ public ModifiedFieldListener(AbstractFormPart generalPart) {
+ this.formPart = generalPart;
+ }
+
+ public void modifyText(ModifyEvent e) {
+ formPart.markDirty();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+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.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.jface.layout.TreeColumnLayout;
+import org.eclipse.jface.viewers.ColumnWeightData;
+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.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * Generic editor property page. Lists all properties of current node as a
+ * complex tree. TODO: enable editing
+ */
+public class GenericPropertyPage extends FormPage implements WorkbenchConstants {
+ // private final static Log log =
+ // LogFactory.getLog(GenericPropertyPage.class);
+
+ // Main business Objects
+ private Node currentNode;
+
+ public GenericPropertyPage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "id", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ ScrolledForm form = managedForm.getForm();
+ form.setText(WorkbenchUiPlugin.getMessage("genericNodePageTitle"));
+ Composite innerBox = form.getBody();
+ //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(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<Property> propList = new ArrayList<Property>();
+ 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() {
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import javax.jcr.query.Query;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+public class JcrQueryEditorInput implements IEditorInput {
+ private final String query;
+ private final String queryType;
+
+ public JcrQueryEditorInput(String query, String queryType) {
+ this.query = query;
+ if (queryType == null)
+ this.queryType = Query.JCR_SQL2;
+ else
+ this.queryType = queryType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return query;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return query;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public String getQueryType() {
+ return queryType;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * A canonical editor input based on a path to a node. In a multirepository
+ * environment, path can be enriched with Repository Alias and workspace
+ */
+
+public class NodeEditorInput implements IEditorInput {
+ private final String path;
+
+ public NodeEditorInput(String path) {
+ this.path = path;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return path;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * Display and edit a given node privilege. For the time being it is completely
+ * JackRabbit specific (and hard coded for this) and will display an empty page
+ * if using any other implementation
+ */
+public class NodePrivilegesPage extends FormPage {
+
+ private Node context;
+
+ private TableViewer viewer;
+
+ public NodePrivilegesPage(FormEditor editor, String title, Node context) {
+ super(editor, "NodePrivilegesPage", title);
+ this.context = context;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ ScrolledForm form = managedForm.getForm();
+ form.setText(WorkbenchUiPlugin.getMessage("nodeRightsManagementPageTitle"));
+ FillLayout layout = new FillLayout();
+ layout.marginHeight = 5;
+ layout.marginWidth = 5;
+ form.getBody().setLayout(layout);
+ if (isJackRabbit())
+ createRightsPart(form.getBody());
+ }
+
+ /** Creates the authorization part */
+ protected void createRightsPart(Composite parent) {
+ Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ table.setLinesVisible(true);
+ table.setHeaderVisible(true);
+ viewer = new TableViewer(table);
+
+ // Group / user name
+ TableViewerColumn column = createTableViewerColumn(viewer, "User/Group Name", 280);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -2290781173498395973L;
+
+ public String getText(Object element) {
+ Node node = (Node) element;
+ try {
+ if (node.hasProperty("rep:principalName"))
+ return node.getProperty("rep:principalName").getString();
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to retrieve " + "principal name on " + node, e);
+ }
+ return "";
+ }
+
+ public Image getImage(Object element) {
+ return null;
+ }
+ });
+
+ // Privileges
+ column = createTableViewerColumn(viewer, "Assigned privileges", 300);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -2290781173498395973L;
+ private String propertyName = "rep:privileges";
+
+ public String getText(Object element) {
+ Node node = (Node) element;
+ try {
+ if (node.hasProperty(propertyName)) {
+ String separator = ", ";
+ Value[] langs = node.getProperty(propertyName).getValues();
+ StringBuilder builder = new StringBuilder();
+ for (Value val : langs) {
+ String currStr = val.getString();
+ builder.append(currStr).append(separator);
+ }
+ if (builder.lastIndexOf(separator) >= 0)
+ return builder.substring(0, builder.length() - separator.length());
+ else
+ return builder.toString();
+
+ }
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to retrieve " + "privileges on " + node, e);
+ }
+ return "";
+ }
+
+ public Image getImage(Object element) {
+ return null;
+ }
+ });
+
+ // Relevant node
+ column = createTableViewerColumn(viewer, "Relevant node", 300);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = 4245522992038244849L;
+
+ public String getText(Object element) {
+ Node node = (Node) element;
+ try {
+ return node.getParent().getParent().getPath();
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable get path for " + node, e);
+ }
+ }
+
+ public Image getImage(Object element) {
+ return null;
+ }
+ });
+
+ viewer.setContentProvider(new RightsContentProvider());
+ viewer.setInput(getEditorSite());
+ }
+
+ protected TableViewerColumn createTableViewerColumn(TableViewer viewer, String title, int bound) {
+ TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+ TableColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setWidth(bound);
+ column.setResizable(true);
+ column.setMoveable(true);
+ return viewerColumn;
+ }
+
+ private class RightsContentProvider implements IStructuredContentProvider {
+ private static final long serialVersionUID = -7631476348552802706L;
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ // TODO JackRabbit specific retrieval of authorization. Clean and
+ // generalize
+ public Object[] getElements(Object inputElement) {
+ try {
+ List<Node> privs = new ArrayList<Node>();
+
+ Node currNode = context;
+ String currPath = currNode.getPath();
+
+ loop: while (true) {
+ if (currNode.hasNode("rep:policy")) {
+ NodeIterator nit = currNode.getNode("rep:policy").getNodes();
+ while (nit.hasNext()) {
+ Node currPrivNode = nit.nextNode();
+ if (currPrivNode.getName().startsWith("allow"))
+ privs.add(currPrivNode);
+ }
+ }
+ if ("/".equals(currPath))
+ break loop;
+ else {
+ currNode = currNode.getParent();
+ currPath = currNode.getPath();
+ }
+ }
+
+ // AccessControlManager acm = context.getSession()
+ // .getAccessControlManager();
+ // AccessControlPolicyIterator acpi = acm
+ // .getApplicablePolicies(context.getPath());
+ //
+ // List<AccessControlPolicy> acps = new
+ // ArrayList<AccessControlPolicy>();
+ // try {
+ // while (true) {
+ // Object obj = acpi.next();
+ // acps.add((AccessControlPolicy) obj);
+ // }
+ // } catch (Exception e) {
+ // // No more elements
+ // }
+ //
+ // AccessControlList acl = ((AccessControlList) acps.get(0));
+ // AccessControlEntry[] entries = acl.getAccessControlEntries();
+
+ return privs.toArray();
+ } catch (Exception e) {
+ throw new EclipseUiException("Cannot retrieve authorization for " + context, e);
+ }
+ }
+ }
+
+ /**
+ * Simply checks if we are using jackrabbit without adding code dependencies
+ */
+ private boolean isJackRabbit() {
+ try {
+ String cname = context.getSession().getClass().getName();
+ return cname.startsWith("org.apache.jackrabbit");
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot check JCR implementation used on " + context, e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+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.cms.ui.CmsConstants;
+import org.argeo.cms.ui.jcr.FullVersioningTreeContentProvider;
+import org.argeo.cms.ui.jcr.JcrDClickListener;
+import org.argeo.cms.ui.jcr.VersionLabelProvider;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.PropertyDiff;
+import org.argeo.jcr.VersionDiff;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+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.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+/**
+ * Offers two main sections : one to display a text area with a summary of all
+ * variations between a version and its predecessor and one tree view that
+ * enable browsing
+ */
+public class NodeVersionHistoryPage extends FormPage implements WorkbenchConstants {
+ // private final static Log log = LogFactory
+ // .getLog(NodeVersionHistoryPage.class);
+
+ // Utils
+ protected DateFormat timeFormatter = new SimpleDateFormat(CmsConstants.DATE_TIME_FORMAT);
+
+ // business objects
+ private Node currentNode;
+
+ // this page UI components
+ private FullVersioningTreeContentProvider nodeContentProvider;
+ private TreeViewer nodesViewer;
+ private FormToolkit tk;
+
+ public NodeVersionHistoryPage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "NodeVersionHistoryPage", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ ScrolledForm form = managedForm.getForm();
+ form.setText(WorkbenchUiPlugin.getMessage("nodeVersionHistoryPageTitle"));
+ tk = managedForm.getToolkit();
+ Composite innerBox = form.getBody();
+ // Composite innerBox = new Composite(body, SWT.NO_FOCUS);
+ GridLayout twt = new GridLayout(1, false);
+ twt.marginWidth = twt.marginHeight = 5;
+ innerBox.setLayout(twt);
+ try {
+ if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
+ tk.createLabel(innerBox, WorkbenchUiPlugin.getMessage("warningUnversionableNode"));
+ } else {
+ createHistorySection(innerBox);
+ createTreeSection(innerBox);
+ }
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Unable to check if node is versionable", e);
+ }
+ }
+
+ protected void createTreeSection(Composite parent) {
+ Section section = tk.createSection(parent, Section.TWISTIE);
+ section.setLayoutData(new GridData(GridData.FILL_BOTH));
+ section.setText(WorkbenchUiPlugin.getMessage("versionTreeSectionTitle"));
+
+ Composite body = tk.createComposite(section, SWT.FILL);
+ section.setClient(body);
+ section.setExpanded(true);
+ body.setLayoutData(new GridData(GridData.FILL_BOTH));
+ body.setLayout(new GridLayout());
+
+ nodeContentProvider = new FullVersioningTreeContentProvider();
+ nodesViewer = createNodeViewer(body, nodeContentProvider);
+ nodesViewer.setInput(currentNode);
+ }
+
+ protected TreeViewer createNodeViewer(Composite parent, final ITreeContentProvider nodeContentProvider) {
+
+ final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
+
+ tmpNodeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ tmpNodeViewer.setContentProvider(nodeContentProvider);
+ tmpNodeViewer.setLabelProvider(new VersionLabelProvider());
+ tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer));
+ return tmpNodeViewer;
+ }
+
+ protected void createHistorySection(Composite parent) {
+
+ // Section Layout
+ Section section = tk.createSection(parent, Section.TWISTIE);
+ section.setLayoutData(new GridData(TableWrapData.FILL_GRAB));
+ TableWrapLayout twt = new TableWrapLayout();
+ section.setLayout(twt);
+
+ // Set title of the section
+ section.setText(WorkbenchUiPlugin.getMessage("versionHistorySectionTitle"));
+
+ final Text styledText = tk.createText(section, "",
+ SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
+ section.setClient(styledText);
+ styledText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB));
+ refreshHistory(styledText);
+ styledText.setEditable(false);
+ section.setExpanded(false);
+
+ AbstractFormPart part = new AbstractFormPart() {
+ public void commit(boolean onSave) {
+ }
+
+ public void refresh() {
+ super.refresh();
+ refreshHistory(styledText);
+ }
+ };
+ getManagedForm().addPart(part);
+ }
+
+ protected void refreshHistory(Text styledText) {
+ try {
+ List<VersionDiff> lst = listHistoryDiff();
+ StringBuffer main = new StringBuffer("");
+
+ for (int i = lst.size() - 1; i >= 0; i--) {
+ if (i == 0)
+ main.append("Creation (");
+ else
+ main.append("Update " + i + " (");
+
+ if (lst.get(i).getUserId() != null)
+ main.append("UserId : " + lst.get(i).getUserId());
+
+ if (lst.get(i).getUserId() != null && lst.get(i).getUpdateTime() != null)
+ main.append(", ");
+
+ if (lst.get(i).getUpdateTime() != null)
+ main.append("Date : " + timeFormatter.format(lst.get(i).getUpdateTime().getTime()) + ")\n");
+
+ StringBuffer buf = new StringBuffer("");
+ Map<String, PropertyDiff> diffs = lst.get(i).getDiffs();
+ for (String prop : diffs.keySet()) {
+ PropertyDiff pd = diffs.get(prop);
+ // String propName = pd.getRelPath();
+ Value refValue = pd.getReferenceValue();
+ Value newValue = pd.getNewValue();
+ String refValueStr = "";
+ String newValueStr = "";
+
+ if (refValue != null) {
+ if (refValue.getType() == PropertyType.DATE) {
+ refValueStr = timeFormatter.format(refValue.getDate().getTime());
+ } else
+ refValueStr = refValue.getString();
+ }
+ if (newValue != null) {
+ if (newValue.getType() == PropertyType.DATE) {
+ newValueStr = timeFormatter.format(newValue.getDate().getTime());
+ } else
+ newValueStr = newValue.getString();
+ }
+
+ if (pd.getType() == PropertyDiff.MODIFIED) {
+ buf.append(prop).append(": ");
+ buf.append(refValueStr);
+ buf.append(" > ");
+ buf.append(newValueStr);
+ buf.append("\n");
+ } else if (pd.getType() == PropertyDiff.ADDED && !"".equals(newValueStr)) {
+ // we don't list property that have been added with an
+ // empty string as value
+ buf.append(prop).append(": ");
+ buf.append(" + ");
+ buf.append(newValueStr);
+ buf.append("\n");
+ } else if (pd.getType() == PropertyDiff.REMOVED) {
+ buf.append(prop).append(": ");
+ buf.append(" - ");
+ buf.append(refValueStr);
+ buf.append("\n");
+ }
+ }
+ buf.append("\n");
+ main.append(buf);
+ }
+ styledText.setText(main.toString());
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot generate history for node", e);
+ }
+ }
+
+ public List<VersionDiff> listHistoryDiff() {
+ try {
+ List<VersionDiff> res = new ArrayList<VersionDiff>();
+ VersionManager versionManager = currentNode.getSession().getWorkspace().getVersionManager();
+ VersionHistory versionHistory = versionManager.getVersionHistory(currentNode.getPath());
+
+ VersionIterator vit = versionHistory.getAllLinearVersions();
+ while (vit.hasNext()) {
+ Version version = vit.nextVersion();
+ Node node = version.getFrozenNode();
+ Version predecessor = null;
+ try {
+ predecessor = version.getLinearPredecessor();
+ } catch (Exception e) {
+ // no predecessor seems to throw an exception even if it
+ // shouldn't...
+ }
+ if (predecessor == null) {// original
+ } else {
+ Map<String, PropertyDiff> diffs = JcrUtils.diffProperties(predecessor.getFrozenNode(), node);
+ if (!diffs.isEmpty()) {
+ String lastUserName = null;
+ Calendar lastUpdate = null;
+ try {
+ if (currentNode.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
+ lastUserName = node.getProperty(Property.JCR_LAST_MODIFIED_BY).getString();
+ lastUpdate = node.getProperty(Property.JCR_LAST_MODIFIED).getDate();
+ } else
+ lastUpdate = version.getProperty(Property.JCR_CREATED).getDate();
+
+ } catch (Exception e) {
+ // Silent that info is optional
+ }
+ VersionDiff vd = new VersionDiff(lastUserName, lastUpdate, diffs);
+ res.add(vd);
+ }
+ }
+ }
+ return res;
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot generate history for node ");
+ }
+
+ }
+
+ @Override
+ public void setActive(boolean active) {
+ super.setActive(active);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.jcr.parts;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * An editor input based on three strings define a node :
+ * <ul>
+ * <li>complete path to the node</li>
+ * <li>the workspace name</li>
+ * <li>the repository alias</li>
+ * </ul>
+ * In a single workspace and/or repository environment, name and alias can be
+ * null.
+ *
+ * Note : unused for the time being.
+ */
+
+public class StringNodeEditorInput implements IEditorInput {
+ private final String path;
+ private final String repositoryAlias;
+ private final String workspaceName;
+
+ /**
+ * In order to implement a generic explorer that supports remote and multi
+ * workspaces repositories, node path can be detailed by these strings.
+ *
+ * @param repositoryAlias
+ * : can be null
+ * @param workspaceName
+ * : can be null
+ * @param path
+ */
+ public StringNodeEditorInput(String repositoryAlias, String workspaceName,
+ String path) {
+ this.path = path;
+ this.repositoryAlias = repositoryAlias;
+ this.workspaceName = workspaceName;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return path;
+ }
+
+ public String getRepositoryAlias() {
+ return repositoryAlias;
+ }
+
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+
+ StringNodeEditorInput other = (StringNodeEditorInput) obj;
+
+ if (!path.equals(other.getPath()))
+ return false;
+
+ String own = other.getWorkspaceName();
+ if ((workspaceName == null && own != null)
+ || (workspaceName != null && (own == null || !workspaceName
+ .equals(own))))
+ return false;
+
+ String ora = other.getRepositoryAlias();
+ if ((repositoryAlias == null && ora != null)
+ || (repositoryAlias != null && (ora == null || !repositoryAlias
+ .equals(ora))))
+ return false;
+
+ return true;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin;
+
+import org.argeo.cms.CmsException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+
+/** Manage transaction and part refresh while updating the security model */
+public class PartStateChanged implements IPartListener, IStartup {
+ // private final static Log log = LogFactory.getLog(PartStateChanged.class);
+ // private IContextActivation contextActivation;
+
+ @Override
+ public void earlyStartup() {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ IWorkbenchPage iwp = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ if (iwp != null)
+ iwp.addPartListener(new PartStateChanged());
+ } catch (Exception e) {
+ throw new CmsException(
+ "Error while registering the PartStateChangedListener",
+ e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void partActivated(IWorkbenchPart part) {
+ // Nothing to do
+ }
+
+ @Override
+ public void partBroughtToTop(IWorkbenchPart part) {
+ // Nothing to do
+ }
+
+ @Override
+ public void partClosed(IWorkbenchPart part) {
+ // Nothing to do
+ }
+
+ @Override
+ public void partDeactivated(IWorkbenchPart part) {
+ // Nothing to do
+ }
+
+ @Override
+ public void partOpened(IWorkbenchPart part) {
+ // Nothing to do
+ }
+}
--- /dev/null
+/*
+ * Argeo Connect - Data management and communications
+ * Copyright (C) 2012 Argeo GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ * Additional permission under GNU GPL version 3 section 7
+ *
+ * If you modify this Program, or any covered work, by linking or combining it
+ * with software covered by the terms of the Eclipse Public License, the
+ * licensors of this Program grant you additional permission to convey the
+ * resulting work. Corresponding Source for a non-source form of such a
+ * combination shall include the source code for the parts of such software
+ * which are used as well as that of the covered work.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin;
+
+import static org.argeo.cms.ui.workbench.WorkbenchUiPlugin.getImageDescriptor;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+/** Shared icons that must be declared programmatically . */
+public class SecurityAdminImages {
+ private final static String PREFIX = "icons/";
+
+ public final static ImageDescriptor ICON_REMOVE_DESC = getImageDescriptor(PREFIX + "delete.png");
+ public final static ImageDescriptor ICON_USER_DESC = getImageDescriptor(PREFIX + "person.png");
+
+ public final static Image ICON_USER = ICON_USER_DESC.createImage();
+ public final static Image ICON_GROUP = getImageDescriptor(PREFIX + "group.png").createImage();
+ public final static Image ICON_WORKGROUP = getImageDescriptor(PREFIX + "workgroup.png").createImage();
+ public final static Image ICON_ROLE = getImageDescriptor(PREFIX + "role.gif").createImage();
+
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin;
+
+import javax.transaction.UserTransaction;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserTransactionProvider;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.services.ISourceProviderService;
+
+/** 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(
+ UserTransaction 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 <a href=
+ * "http://www.mkyong.com/regular-expressions/how-to-validate-email-address-with-regular-expression/"
+ * >this tip</a>.
+ */
+ 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,})$";
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin;
+
+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);
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
+import org.argeo.osgi.useradmin.UserAdminConf;
+import org.osgi.framework.ServiceReference;
+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<UserAdmin> userAdminServiceReference;
+ private UserTransaction userTransaction;
+
+ // First effort to simplify UX while managing users and groups
+ public final static boolean COMMIT_ON_SAVE = true;
+
+ // Registered listeners
+ List<UserAdminListener> listeners = new ArrayList<UserAdminListener>();
+
+ /**
+ * Starts a transaction if necessary. Should always been called together
+ * with {@link UserAdminWrapper#commitOrNotifyTransactionStateChange()} once
+ * the security model changes have been performed.
+ */
+ public UserTransaction beginTransactionIfNeeded() {
+ try {
+ // UserTransaction userTransaction = getUserTransaction();
+ if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION) {
+ 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.getStatus() == Status.STATUS_NO_TRANSACTION)
+ 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<String, String> getKnownBaseDns(boolean onlyWritable) {
+ Map<String, String> dns = new HashMap<String, String>();
+ for (String uri : userAdminServiceReference.getPropertyKeys()) {
+ if (!uri.startsWith("/"))
+ continue;
+ Dictionary<String, ?> 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;
+ dns.put(baseDn, uri);
+ }
+ return dns;
+ }
+
+ public UserAdmin getUserAdmin() {
+ return userAdmin;
+ }
+
+ public UserTransaction getUserTransaction() {
+ return userTransaction;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdmin(UserAdmin userAdmin) {
+ this.userAdmin = userAdmin;
+ }
+
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+ public void setUserAdminServiceReference(
+ ServiceReference<UserAdmin> userAdminServiceReference) {
+ this.userAdminServiceReference = userAdminServiceReference;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditorInput;
+import org.argeo.cms.util.UserAdminUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+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 extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".deleteGroups";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ @SuppressWarnings("unchecked")
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection.isEmpty())
+ return null;
+
+ List<Group> groups = new ArrayList<Group>();
+ Iterator<Group> it = ((IStructuredSelection) selection).iterator();
+ StringBuilder builder = new StringBuilder();
+ while (it.hasNext()) {
+ Group currGroup = it.next();
+ String groupName = UserAdminUtils.getUserLocalId(currGroup.getName());
+ // TODO add checks
+ builder.append(groupName).append("; ");
+ groups.add(currGroup);
+ }
+
+ if (!MessageDialog.openQuestion(HandlerUtil.getActiveShell(event), "Delete Groups", "Are you sure that you "
+ + "want to delete these groups?\n" + builder.substring(0, builder.length() - 2)))
+ return null;
+
+ userAdminWrapper.beginTransactionIfNeeded();
+ UserAdmin userAdmin = userAdminWrapper.getUserAdmin();
+ IWorkbenchPage iwp = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
+ for (Group group : groups) {
+ 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 : groups) {
+ userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, group));
+ }
+
+ return null;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.userAdminWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditorInput;
+import org.argeo.cms.util.UserAdminUtils;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+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 extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".deleteUsers";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ @SuppressWarnings("unchecked")
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection.isEmpty())
+ return null;
+
+ Iterator<User> it = ((IStructuredSelection) selection).iterator();
+ List<User> users = new ArrayList<User>();
+ StringBuilder builder = new StringBuilder();
+
+ while (it.hasNext()) {
+ User currUser = it.next();
+ String userName = UserAdminUtils.getUserLocalId(currUser.getName());
+ if (UserAdminUtils.isCurrentUser(currUser)) {
+ MessageDialog.openError(HandlerUtil.getActiveShell(event), "Deletion forbidden",
+ "You cannot delete your own user this way.");
+ return null;
+ }
+ builder.append(userName).append("; ");
+ users.add(currUser);
+ }
+
+ if (!MessageDialog.openQuestion(HandlerUtil.getActiveShell(event), "Delete Users",
+ "Are you sure that you want to delete these users?\n" + builder.substring(0, builder.length() - 2)))
+ return null;
+
+ userAdminWrapper.beginTransactionIfNeeded();
+ UserAdmin userAdmin = userAdminWrapper.getUserAdmin();
+ IWorkbenchPage iwp = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
+
+ for (User user : users) {
+ 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 : users) {
+ userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, user));
+ }
+ return null;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.userAdminWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.GroupsView;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UsersView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Retrieve the active view or editor and call forceRefresh method if defined */
+public class ForceRefresh extends AbstractHandler {
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ IWorkbenchWindow iww = HandlerUtil.getActiveWorkbenchWindow(event);
+ if (iww == null)
+ return null;
+ IWorkbenchPage activePage = iww.getActivePage();
+ IWorkbenchPart part = activePage.getActivePart();
+ if (part instanceof UsersView)
+ ((UsersView) part).refresh();
+ else if (part instanceof GroupsView)
+ ((GroupsView) part).refresh();
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import java.util.Dictionary;
+import java.util.Map;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.osgi.useradmin.UserAdminConf;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.handlers.HandlerUtil;
+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 extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".newGroup";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ NewGroupWizard newGroupWizard = new NewGroupWizard();
+ newGroupWizard.setWindowTitle("Group creation");
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), 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, ArgeoNames {
+ 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<String, String> getDns() {
+ return userAdminWrapper.getKnownBaseDns(true);
+ }
+
+ private String getDn(String cn) {
+ Map<String, String> dns = getDns();
+ String bdn = baseDnCmb.getText();
+ if (EclipseUiUtils.notEmpty(bdn)) {
+ Dictionary<String, ?> props = UserAdminConf.uriAsProperties(dns
+ .get(bdn));
+ String dn = LdapAttrs.cn.name() + "=" + cn + ","
+ + UserAdminConf.groupBase.getValue(props) + "," + bdn;
+ return dn;
+ }
+ return null;
+ }
+
+ private void initialiseDnCmb(Combo combo) {
+ Map<String, String> 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;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.UiAdminUtils;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.osgi.useradmin.UserAdminConf;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.handlers.HandlerUtil;
+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 extends AbstractHandler {
+ // private final static Log log = LogFactory.getLog(NewUser.class);
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".newUser";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ NewUserWizard newUserWizard = new NewUserWizard();
+ newUserWizard.setWindowTitle("User creation");
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), 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, ArgeoNames {
+ 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<String, String> getDns() {
+ return userAdminWrapper.getKnownBaseDns(true);
+ }
+
+ private String getDn(String uid) {
+ Map<String, String> dns = getDns();
+ String bdn = baseDnCmb.getText();
+ if (EclipseUiUtils.notEmpty(bdn)) {
+ Dictionary<String, ?> props = UserAdminConf.uriAsProperties(dns
+ .get(bdn));
+ String dn = LdapAttrs.uid.name() + "=" + uid + ","
+ + UserAdminConf.userBase.getValue(props) + "," + bdn;
+ return dn;
+ }
+ return null;
+ }
+
+ private void initialiseDnCmb(Combo combo) {
+ Map<String, String> 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<Rdn> 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;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Save the currently edited Argeo user. */
+public class SaveArgeoUser extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".saveArgeoUser";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ try {
+ IWorkbenchPart iwp = HandlerUtil.getActiveWorkbenchWindow(event)
+ .getActivePage().getActivePart();
+ if (!(iwp instanceof IEditorPart))
+ return null;
+ IEditorPart editor = (IEditorPart) iwp;
+ editor.doSave(null);
+ } catch (Exception e) {
+ MessageDialog.openError(Display.getDefault().getActiveShell(),
+ "Error", "Cannot save user: " + e.getMessage());
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserBatchUpdateWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Launch a wizard to perform batch process on users */
+public class UserBatchUpdate extends AbstractHandler {
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper uaWrapper;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ UserBatchUpdateWizard wizard = new UserBatchUpdateWizard(uaWrapper);
+ wizard.setWindowTitle("User batch processing");
+ WizardDialog dialog = new WizardDialog(
+ HandlerUtil.getActiveShell(event), wizard);
+ dialog.open();
+ return null;
+ }
+
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.uaWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.commands;
+
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.UiAdminUtils;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.osgi.service.useradmin.UserAdminEvent;
+
+/** Manage the transaction that is bound to the current perspective */
+public class UserTransactionHandler extends AbstractHandler {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".userTransactionHandler";
+
+ public final static String PARAM_COMMAND_ID = "param.commandId";
+
+ public final static String TRANSACTION_BEGIN = "transaction.begin";
+ public final static String TRANSACTION_COMMIT = "transaction.commit";
+ public final static String TRANSACTION_ROLLBACK = "transaction.rollback";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String commandId = event.getParameter(PARAM_COMMAND_ID);
+ final UserTransaction userTransaction = userAdminWrapper
+ .getUserTransaction();
+ try {
+ if (TRANSACTION_BEGIN.equals(commandId)) {
+ if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION)
+ throw new CmsException("A transaction already exists");
+ else
+ userTransaction.begin();
+ } else if (TRANSACTION_COMMIT.equals(commandId)) {
+ if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
+ throw new CmsException("No transaction.");
+ else
+ userTransaction.commit();
+ } else if (TRANSACTION_ROLLBACK.equals(commandId)) {
+ if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
+ throw new CmsException("No transaction to rollback.");
+ else {
+ userTransaction.rollback();
+ userAdminWrapper.notifyListeners(new UserAdminEvent(null,
+ UserAdminEvent.ROLE_CHANGED, null));
+ }
+ }
+
+ UiAdminUtils.notifyTransactionStateChange(userTransaction);
+ // Try to remove invalid thread access errors when managing users.
+ // HandlerUtil.getActivePart(event).getSite().getShell().getDisplay()
+ // .asyncExec(new Runnable() {
+ // @Override
+ // public void run() {
+ // UiAdminUtils
+ // .notifyTransactionStateChange(userTransaction);
+ // }
+ // });
+
+ } catch (CmsException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CmsException("Unable to call " + commandId + " on "
+ + userTransaction, e);
+ }
+ return null;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.userAdminWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/** Editor input for an Argeo user. */
+public class ArgeoUserEditorInput implements IEditorInput {
+ private final String username;
+
+ public ArgeoUserEditorInput(String username) {
+ this.username = username;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return username != null;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return username != null ? username : "<new user>";
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return username != null ? username : "<new user>";
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ArgeoUserEditorInput))
+ return false;
+ if (((ArgeoUserEditorInput) obj).getUsername() == null)
+ return false;
+ return ((ArgeoUserEditorInput) obj).getUsername().equals(username);
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import static org.argeo.cms.util.UserAdminUtils.setProperty;
+import static org.argeo.naming.LdapAttrs.businessCategory;
+import static org.argeo.naming.LdapAttrs.description;
+import static org.argeo.node.NodeInstance.WORKGROUP;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.transaction.UserTransaction;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.CmsWorkbenchStyles;
+import org.argeo.cms.ui.workbench.internal.useradmin.SecurityAdminImages;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor.GroupChangeListener;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor.MainInfoListener;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.CommonNameLP;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.MailLP;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.RoleIconLP;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserFilter;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserTableDefaultDClickListener;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.eclipse.ui.ColumnDefinition;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.parts.LdifUsersTable;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.node.NodeInstance;
+import org.argeo.node.NodeUtils;
+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.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Cursor;
+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.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.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 main properties of a given group */
+public class GroupMainPage extends FormPage implements ArgeoNames {
+ final static String ID = "GroupEditor.mainPage";
+
+ private final UserEditor editor;
+ private final NodeInstance nodeInstance;
+ private final UserAdminWrapper userAdminWrapper;
+ private final Session session;
+
+ 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
+ public void dispose() {
+ JcrUtils.logoutQuietly(session);
+ super.dispose();
+ }
+
+ /** Creates the general section */
+ protected void appendOverviewPart(final Composite parent, final Group group) {
+ FormToolkit tk = getManagedForm().getToolkit();
+ Composite body = addSection(tk, parent);
+ // GridLayout layout = new GridLayout(5, false);
+ GridLayout layout = new GridLayout(2, false);
+ body.setLayout(layout);
+
+ String cn = UserAdminUtils.getProperty(group, LdapAttrs.cn.name());
+ createReadOnlyLT(body, "Name", cn);
+ // Text dnTxt = 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, false, false, 2, 1));
+ final Text descTxt = new Text(body, SWT.LEAD | SWT.MULTI | SWT.WRAP | SWT.BORDER);
+ GridData gd = EclipseUiUtils.fillAll();
+ 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 SectionPart((Section) body.getParent()) {
+
+ private MainInfoListener listener;
+
+ @Override
+ public void initialize(IManagedForm form) {
+ super.initialize(form);
+ listener = editor.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 = NodeUtils.getGroupHome(session, cn);
+ if (workgroupHome == null)
+ markAsWorkgroupLk.setText("<a>Mark as workgroup</a>");
+ 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 = NodeUtils.getGroupHome(session, cn);
+ if (workgroupHome != null)
+ return; // already marked as workgroup, do nothing
+ else
+ try {
+ // improve transaction management
+ userAdminWrapper.beginTransactionIfNeeded();
+ nodeInstance.createWorkgroup(new LdapName(group.getName()));
+ setProperty(group, businessCategory, WORKGROUP);
+ userAdminWrapper.commitOrNotifyTransactionStateChange();
+ userAdminWrapper
+ .notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_CHANGED, group));
+ part.refresh();
+ } catch (InvalidNameException e1) {
+ throw new CmsException("Cannot create Workgroup for " + group.toString(), e1);
+ }
+
+ }
+ }
+ });
+
+ ModifyListener defaultListener = editor.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) {
+ FormToolkit tk = getManagedForm().getToolkit();
+ Section section = tk.createSection(parent, Section.TITLE_BAR);
+ section.setText("Members");
+ section.setLayoutData(EclipseUiUtils.fillAll());
+
+ Composite body = new Composite(section, SWT.NO_FOCUS);
+ section.setClient(body);
+ body.setLayoutData(EclipseUiUtils.fillAll());
+
+ LdifUsersTable userTableViewerCmp = createMemberPart(body, group);
+
+ SectionPart part = new GroupMembersPart(section, userTableViewerCmp);
+ getManagedForm().addPart(part);
+ addRemoveAbitily(part, userTableViewerCmp.getTableViewer(), group);
+ }
+
+ public LdifUsersTable createMemberPart(Composite parent, Group group) {
+ parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
+
+ // Define the displayed columns
+ List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+ 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());
+ int operations = DND.DROP_COPY | DND.DROP_MOVE;
+ Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
+ userViewer.addDropSupport(operations, tt,
+ new GroupDropListener(userAdminWrapper, userViewerCmp, (Group) editor.getDisplayedUser()));
+
+ 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<User> listFilteredElements(String filter) {
+ // reload user and set it in the editor
+ Group group = (Group) editor.getDisplayedUser();
+ Role[] roles = group.getMembers();
+ List<User> users = new ArrayList<User>();
+ 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 addRemoveAbitily(SectionPart sectionPart, TableViewer userViewer, Group group) {
+ Section section = sectionPart.getSection();
+ ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
+ ToolBar toolbar = toolBarManager.createControl(section);
+ final Cursor handCursor = new Cursor(section.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<User> it = ((IStructuredSelection) selection).iterator();
+ List<User> users = new ArrayList<User>();
+ 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 SectionPart {
+ private final LdifUsersTable userViewer;
+ // private final Group group;
+
+ private GroupChangeListener listener;
+
+ public GroupMembersPart(Section section, LdifUsersTable userViewer) {
+ super(section);
+ this.userViewer = userViewer;
+ // this.group = group;
+ }
+
+ @Override
+ public void initialize(IManagedForm form) {
+ super.initialize(form);
+ listener = editor.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<User> myMemberships = editor.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<User> newGroupMemberships = editor.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
+ UserTransaction transaction = userAdminWrapper.beginTransactionIfNeeded();
+ User user = (User) role;
+ myGroup.addMember(user);
+ if (UserAdminWrapper.COMMIT_ON_SAVE)
+ try {
+ transaction.commit();
+ } catch (Exception e) {
+ throw new CmsException("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));
+ // CmsUtils.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);
+ CmsUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT);
+ return text;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.CurrentUser;
+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.naming.LdapAttrs;
+import org.argeo.naming.LdapObjs;
+import org.argeo.node.NodeConstants;
+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 extends ViewPart implements ArgeoNames {
+ private final static Log log = LogFactory.getLog(GroupsView.class);
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".groupsView";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ // UI Objects
+ private LdifUsersTable groupTableViewerCmp;
+ private TableViewer userViewer;
+ private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+
+ private UserAdminListener listener;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ 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());
+ getViewSite().setSelectionProvider(userViewer);
+
+ // 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(NodeConstants.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(NodeConstants.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<User> 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(")");
+ if (!showSystemRoles)
+ builder.append("(!(").append(LdapAttrs.DN).append("=*").append(NodeConstants.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(NodeConstants.ROLES_BASEDN).append(")))");
+ else
+ builder.append("(").append(LdapAttrs.objectClass.name()).append("=")
+ .append(LdapObjs.groupOfNames.name()).append(")");
+
+ }
+ roles = userAdminWrapper.getUserAdmin().getRoles(builder.toString());
+ } catch (InvalidSyntaxException e) {
+ throw new CmsException("Unable to get roles with filter: " + filter, e);
+ }
+ List<User> users = new ArrayList<User>();
+ 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();
+ }
+
+ // Override generic view methods
+ @Override
+ public void dispose() {
+ userAdminWrapper.removeListener(listener);
+ super.dispose();
+ }
+
+ @Override
+ public void setFocus() {
+ groupTableViewerCmp.setFocus();
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.userAdminWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.ui.workbench.internal.useradmin.UiAdminUtils;
+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.MailLP;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserNameLP;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.eclipse.ui.ColumnDefinition;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.parts.LdifUsersTable;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.naming.LdapObjs;
+import org.argeo.node.NodeConstants;
+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 Log log = LogFactory.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<String, String> commands = new HashMap<String, String>() {
+ 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;
+ UserTransaction ut = userAdminWrapper.getUserTransaction();
+ try {
+ if (ut.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION
+ && !MessageDialog.openConfirm(getShell(), "Existing Transaction",
+ "A user transaction is already existing, " + "are you sure you want to proceed ?"))
+ return false;
+ } catch (SystemException e) {
+ throw new CmsException("Cannot get user transaction state " + "before user batch update", e);
+ }
+
+ // 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<User> usersToUpdate;
+
+ public ResetPassword(UserAdminWrapper userAdminWrapper, List<User> 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 {
+ 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();
+ }
+ }
+ }
+ }
+
+ private class ResetEmail {
+ private String newEmail;
+ private UserAdminWrapper userAdminWrapper;
+ private List<User> usersToUpdate;
+
+ public ResetEmail(UserAdminWrapper userAdminWrapper, List<User> 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 {
+ 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 block, the system might be in a dirty state");
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ // @SuppressWarnings("unused")
+ // private class AddToGroup extends UpdateJob {
+ // private String groupID;
+ // private Session session;
+ //
+ // public AddToGroup(Session session, List<Node> 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<User> usersToUpdate;
+ //
+ // protected abstract void doUpdate(User user);
+ //
+ // public UpdateJob(UserAdminWrapper userAdminWrapper,
+ // List<User> 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<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+ 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(NodeConstants.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<User> 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<User> 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<User> users = new ArrayList<User>();
+ 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<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+ 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(NodeConstants.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<User> listFilteredElements(String filter) {
+ return userListPage.getSelectedUsers();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Repository;
+
+import org.argeo.cms.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.util.UserAdminUtils;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.node.NodeInstance;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.editor.FormEditor;
+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 class UserEditor extends FormEditor {
+ private static final long serialVersionUID = 8357851520380820241L;
+
+ public final static String USER_EDITOR_ID = WorkbenchUiPlugin.PLUGIN_ID + ".userEditor";
+ public final static String GROUP_EDITOR_ID = WorkbenchUiPlugin.PLUGIN_ID + ".groupEditor";
+
+ /* DEPENDENCY INJECTION */
+ private Repository repository;
+ private UserAdminWrapper userAdminWrapper;
+ private UserAdmin userAdmin;
+ private NodeInstance nodeInstance;
+
+ // Context
+ private User user;
+ private String username;
+
+ private NameChangeListener listener;
+
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ super.init(site, input);
+ this.userAdmin = userAdminWrapper.getUserAdmin();
+ username = ((UserEditorInput) getEditorInput()).getUsername();
+ user = (User) userAdmin.getRole(username);
+
+ listener = new NameChangeListener(site.getShell().getDisplay());
+ userAdminWrapper.addListener(listener);
+ updateEditorTitle(null);
+ }
+
+ /**
+ * returns the list of all authorization for the given user or of the current
+ * displayed user if parameter is null
+ */
+ protected List<User> getFlatGroups(User aUser) {
+ Authorization currAuth;
+ if (aUser == null)
+ currAuth = userAdmin.getAuthorization(this.user);
+ else
+ currAuth = userAdmin.getAuthorization(aUser);
+
+ String[] roles = currAuth.getRoles();
+
+ List<User> groups = new ArrayList<User>();
+ for (String roleStr : roles) {
+ User currRole = (User) userAdmin.getRole(roleStr);
+ if (currRole != null && !groups.contains(currRole))
+ groups.add(currRole);
+ }
+ return groups;
+ }
+
+ /** 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 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);
+ }
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor) {
+ userAdminWrapper.beginTransactionIfNeeded();
+ commitPages(true);
+ userAdminWrapper.commitOrNotifyTransactionStateChange();
+ firePropertyChange(PROP_DIRTY);
+ userAdminWrapper.notifyListeners(new UserAdminEvent(null, UserAdminEvent.ROLE_REMOVED, user));
+ }
+
+ @Override
+ public void doSaveAs() {
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ @Override
+ public void dispose() {
+ userAdminWrapper.removeListener(listener);
+ super.dispose();
+ }
+
+ // CONTROLERS FOR THIS EDITOR AND ITS PAGES
+
+ private 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;
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ public void setNodeInstance(NodeInstance nodeInstance) {
+ this.nodeInstance = nodeInstance;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * Editor input for an user defined by unique name (usually a distinguished
+ * name).
+ */
+public class UserEditorInput implements IEditorInput {
+ private final String username;
+
+ public UserEditorInput(String username) {
+ this.username = username;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+
+ public boolean exists() {
+ return username != null;
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public String getName() {
+ return username != null ? username : "<new user>";
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ public String getToolTipText() {
+ return username != null ? username : "<new user>";
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof UserEditorInput))
+ return false;
+ if (((UserEditorInput) obj).getUsername() == null)
+ return false;
+ return ((UserEditorInput) obj).getUsername().equals(username);
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import static org.argeo.cms.util.UserAdminUtils.getProperty;
+import static org.argeo.naming.LdapAttrs.cn;
+import static org.argeo.naming.LdapAttrs.givenName;
+import static org.argeo.naming.LdapAttrs.mail;
+import static org.argeo.naming.LdapAttrs.sn;
+import static org.argeo.naming.LdapAttrs.uid;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.ui.workbench.CmsWorkbenchStyles;
+import org.argeo.cms.ui.workbench.internal.useradmin.SecurityAdminImages;
+import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor.GroupChangeListener;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor.MainInfoListener;
+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.UserFilter;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserTableDefaultDClickListener;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.eclipse.ui.ColumnDefinition;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.parts.LdifUsersTable;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.node.NodeConstants;
+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.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Cursor;
+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.Link;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+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.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 UserMainPage extends FormPage implements ArgeoNames {
+ final static String ID = "UserEditor.mainPage";
+
+ 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);
+ }
+
+ /** 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 = tk.createComposite(section, SWT.WRAP);
+ body.setLayoutData(EclipseUiUtils.fillAll());
+ section.setClient(body);
+ // body.setLayout(new GridLayout(6, false));
+ body.setLayout(new GridLayout(2, false));
+
+ Text commonName = createReadOnlyLT(tk, body, "Name", getProperty(user, cn));
+ Text distinguishedName = createReadOnlyLT(tk, body, "Login", getProperty(user, uid));
+ Text firstName = createLT(tk, body, "First name", getProperty(user, givenName));
+ Text lastName = createLT(tk, body, "Last name", getProperty(user, sn));
+ Text email = createLT(tk, body, "Email", getProperty(user, mail));
+
+ Link resetPwdLk = new Link(body, SWT.NONE);
+ if (!UserAdminUtils.isCurrentUser(user)) {
+ resetPwdLk.setText("<a>Reset password</a>");
+ }
+ resetPwdLk.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ // create form part (controller)
+ AbstractFormPart part = new SectionPart((Section) body.getParent()) {
+ private MainInfoListener listener;
+
+ @Override
+ public void initialize(IManagedForm form) {
+ super.initialize(form);
+ listener = editor.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);
+ editor.updateEditorTitle(cn);
+ }
+ };
+ firstName.addModifyListener(cnML);
+ lastName.addModifyListener(cnML);
+
+ ModifyListener defaultListener = editor.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(tk, 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(FormToolkit tk, 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(tk, body, "New password", "");
+ password2 = createLP(tk, 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) {
+ FormToolkit tk = getManagedForm().getToolkit();
+ Section section = addSection(tk, parent, "Roles");
+ Composite body = (Composite) section.getClient();
+ body.setLayout(EclipseUiUtils.noSpaceGridLayout());
+
+ // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
+
+ // Displayed columns
+ List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+ 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());
+ 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);
+
+ SectionPart part = new SectionPart((Section) body.getParent()) {
+
+ private GroupChangeListener listener;
+
+ @Override
+ public void initialize(IManagedForm form) {
+ super.initialize(form);
+ listener = editor.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(part, userViewer, user);
+ 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(NodeConstants.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<User> listFilteredElements(String filter) {
+ List<User> users = (List<User>) editor.getFlatGroups(null);
+ List<User> filteredUsers = new ArrayList<User>();
+ 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 addRemoveAbitily(SectionPart sectionPart, TableViewer userViewer, User user) {
+ Section section = sectionPart.getSection();
+ ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
+ ToolBar toolbar = toolBarManager.createControl(section);
+ final Cursor handCursor = new Cursor(section.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();
+ }
+ }
+ });
+
+ 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<Group> it = ((IStructuredSelection) selection).iterator();
+ List<Group> groups = new ArrayList<Group>();
+ 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;
+ }
+
+ /** Creates label and multiline text. */
+ Text createLMT(FormToolkit toolkit, Composite body, String label, String value) {
+ Label lbl = toolkit.createLabel(body, label);
+ lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
+ return text;
+ }
+
+ /** Creates label and password. */
+ Text createLP(FormToolkit toolkit, Composite body, String label, String value) {
+ Label lbl = toolkit.createLabel(body, label);
+ lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
+ Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ return text;
+ }
+
+ /** Creates label and text. */
+ Text createLT(FormToolkit toolkit, Composite parent, String label, String value) {
+ 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));
+ CmsUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT);
+ return text;
+ }
+
+ Text createReadOnlyLT(FormToolkit toolkit, Composite parent, String label, String value) {
+ 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);
+ CmsUtils.style(text, CmsWorkbenchStyles.WORKBENCH_FORM_TEXT);
+ return text;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.internal.useradmin.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.argeo.cms.ArgeoNames;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.CurrentUser;
+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.MailLP;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserDragListener;
+import org.argeo.cms.ui.workbench.internal.useradmin.providers.UserNameLP;
+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.naming.LdapAttrs;
+import org.argeo.naming.LdapObjs;
+import org.argeo.node.NodeConstants;
+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.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 users with filter - based on Ldif userAdmin */
+public class UsersView extends ViewPart implements ArgeoNames {
+ // private final static Log log = LogFactory.getLog(UsersView.class);
+
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".usersView";
+
+ /* DEPENDENCY INJECTION */
+ private UserAdminWrapper userAdminWrapper;
+
+ // UI Objects
+ private LdifUsersTable userTableViewerCmp;
+ private TableViewer userViewer;
+ private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+
+ private UserAdminListener listener;
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ 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(NodeConstants.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());
+ 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<User> 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<User> users = new ArrayList<User>();
+ 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
+ @Override
+ public void dispose() {
+ userAdminWrapper.removeListener(listener);
+ super.dispose();
+ }
+
+ @Override
+ public void setFocus() {
+ userTableViewerCmp.setFocus();
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdminWrapper(UserAdminWrapper userAdminWrapper) {
+ this.userAdminWrapper = userAdminWrapper;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.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);
+ }
+
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import org.argeo.cms.util.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);
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.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());
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import org.argeo.cms.ui.workbench.internal.useradmin.SecurityAdminImages;
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.NodeInstance;
+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(NodeConstants.ROLES_BASEDN))
+ return SecurityAdminImages.ICON_ROLE;
+ else if (user.getType() == Role.GROUP) {
+ String businessCategory = UserAdminUtils.getProperty(user, LdapAttrs.businessCategory);
+ if (businessCategory != null && businessCategory.equals(NodeInstance.WORKGROUP))
+ return SecurityAdminImages.ICON_WORKGROUP;
+ return SecurityAdminImages.ICON_GROUP;
+ } else
+ return SecurityAdminImages.ICON_USER;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.util.UserAdminUtils;
+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);
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.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) {
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty;
+
+import org.argeo.cms.util.UserAdminUtils;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.node.NodeConstants;
+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(".*(" + NodeConstants.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;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.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();
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditor;
+import org.argeo.cms.ui.workbench.internal.useradmin.parts.UserEditorInput;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+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 {
+ public void doubleClick(DoubleClickEvent evt) {
+ if (evt.getSelection().isEmpty())
+ return;
+ Object obj = ((IStructuredSelection) evt.getSelection())
+ .getFirstElement();
+ User user = (User) obj;
+ IWorkbenchWindow iww = WorkbenchUiPlugin.getDefault().getWorkbench()
+ .getActiveWorkbenchWindow();
+ IWorkbenchPage iwp = iww.getActivePage();
+ UserEditorInput uei = new UserEditorInput(user.getName());
+
+ try {
+ // Works around the fact that dynamic setting of the editor icon
+ // causes NPE after a login/logout on RAP
+ if (user instanceof Group)
+ iwp.openEditor(uei, UserEditor.GROUP_EDITOR_ID);
+ else
+ iwp.openEditor(uei, UserEditor.USER_EDITOR_ID);
+ } catch (PartInitException pie) {
+ throw new CmsException("Unable to open UserEditor for " + user, pie);
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.internal.useradmin.providers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.eclipse.ui.AbstractSourceProvider;
+import org.eclipse.ui.ISources;
+
+/** Observe and notify UI on UserTransaction state changes */
+public class UserTransactionProvider extends AbstractSourceProvider {
+ private final static Log log = LogFactory
+ .getLog(UserTransactionProvider.class);
+
+ public final static String TRANSACTION_STATE = WorkbenchUiPlugin.PLUGIN_ID
+ + ".userTransactionState";
+ public final static String STATUS_ACTIVE = "status.active";
+ public final static String STATUS_NO_TRANSACTION = "status.noTransaction";
+
+ /* DEPENDENCY INJECTION */
+ private UserTransaction userTransaction;
+
+ @Override
+ public String[] getProvidedSourceNames() {
+ return new String[] { TRANSACTION_STATE };
+ }
+
+ @Override
+ public Map<String, String> getCurrentState() {
+ Map<String, String> currentState = new HashMap<String, String>(1);
+ currentState.put(TRANSACTION_STATE, getInternalCurrentState());
+ return currentState;
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ private String getInternalCurrentState() {
+ try {
+ String transactionState;
+ if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
+ transactionState = STATUS_NO_TRANSACTION;
+ else
+ // if (userTransaction.getStatus() == Status.STATUS_ACTIVE)
+ transactionState = STATUS_ACTIVE;
+ return transactionState;
+ } catch (Exception e) {
+ throw new CmsException("Unable to begin transaction", e);
+ }
+ }
+
+ /** Publishes the ability to notify a state change */
+ public void fireTransactionStateChange() {
+ try {
+ fireSourceChanged(ISources.WORKBENCH, TRANSACTION_STATE,
+ getInternalCurrentState());
+ } catch (Exception e) {
+ log.warn("Cannot fire transaction state change event. Caught exception: "
+ + e.getClass().getCanonicalName() + " - " + e.getMessage());
+ }
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.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.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.ChildNodesPage;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.GenericNodeEditorInput;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.GenericNodePage;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.GenericPropertyPage;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.NodePrivilegesPage;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.NodeVersionHistoryPage;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.FormEditor;
+
+/** Default form editor for a Jcr {@link Node} */
+public class DefaultNodeEditor extends FormEditor {
+ private static final long serialVersionUID = 8322127770921612239L;
+
+ // private final static Log log =
+ // LogFactory.getLog(GenericNodeEditor.class);
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".defaultNodeEditor";
+
+ private Node currentNode;
+
+ private GenericNodePage genericNodePage;
+ private GenericPropertyPage genericPropertyPage;
+ private ChildNodesPage childNodesPage;
+ private NodePrivilegesPage nodeRightsManagementPage;
+ private NodeVersionHistoryPage nodeVersionHistoryPage;
+
+ public void init(IEditorSite site, IEditorInput input)
+ throws PartInitException {
+ super.init(site, input);
+ GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput();
+ currentNode = nei.getCurrentNode();
+ this.setPartName(JcrUtils.lastPathElement(nei.getPath()));
+ }
+
+ @Override
+ protected void addPages() {
+ try {
+ genericPropertyPage = new GenericPropertyPage(this,
+ WorkbenchUiPlugin.getMessage("genericNodePageTitle"),
+ currentNode);
+ addPage(genericPropertyPage);
+
+ childNodesPage = new ChildNodesPage(this,
+ WorkbenchUiPlugin.getMessage("childNodesPageTitle"),
+ currentNode);
+ addPage(childNodesPage);
+
+ AccessControlManager accessControlManager = currentNode
+ .getSession().getAccessControlManager();
+ List<Privilege> privileges = new ArrayList<Privilege>();
+ privileges.add(accessControlManager
+ .privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL));
+ if (accessControlManager.hasPrivileges(currentNode.getPath(),
+ privileges.toArray(new Privilege[0]))) {
+ nodeRightsManagementPage = new NodePrivilegesPage(this,
+ WorkbenchUiPlugin
+ .getMessage("nodeRightsManagementPageTitle"),
+ currentNode);
+ addPage(nodeRightsManagementPage);
+ }
+ if (currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
+ nodeVersionHistoryPage = new NodeVersionHistoryPage(this,
+ WorkbenchUiPlugin
+ .getMessage("nodeVersionHistoryPageTitle"),
+ currentNode);
+ addPage(nodeVersionHistoryPage);
+ }
+
+ privileges = new ArrayList<Privilege>();
+ privileges.add(accessControlManager
+ .privilegeFromName(Privilege.JCR_ALL));
+ if (accessControlManager.hasPrivileges(currentNode.getPath(),
+ privileges.toArray(new Privilege[0]))) {
+ genericNodePage = new GenericNodePage(
+ this,
+ WorkbenchUiPlugin.getMessage("propertyEditorPageTitle"),
+ currentNode);
+ addPage(genericNodePage);
+ }
+
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("Cannot get node info for "
+ + currentNode, e);
+ } catch (PartInitException e) {
+ throw new EclipseUiException("Cannot add page "
+ + "on node editor for " + currentNode, e);
+ }
+ }
+
+ @Override
+ public void doSaveAs() {
+ // unused compulsory method
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor) {
+ try {
+ // Automatically commit all pages of the editor
+ commitPages(true);
+ firePropertyChange(PROP_DIRTY);
+ } catch (Exception e) {
+ throw new EclipseUiException("Error while saving node", e);
+ }
+
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ Node getCurrentNode() {
+ return currentNode;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.jcr;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.AbstractJcrQueryEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+
+/** Enables end user to type and execute any JCR query. */
+public class GenericJcrQueryEditor extends AbstractJcrQueryEditor {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
+ + ".genericJcrQueryEditor";
+
+ private Text queryField;
+
+ @Override
+ public void createQueryForm(Composite parent) {
+ parent.setLayout(new GridLayout(1, false));
+
+ queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP);
+ queryField.setText(initialQuery);
+ queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Button execute = new Button(parent, SWT.PUSH);
+ execute.setText("Execute");
+
+ Listener executeListener = new Listener() {
+ private static final long serialVersionUID = -918256291554301699L;
+
+ public void handleEvent(Event event) {
+ executeQuery(queryField.getText());
+ }
+ };
+
+ execute.addListener(SWT.Selection, executeListener);
+ // queryField.addListener(SWT.DefaultSelection, executeListener);
+ }
+
+ @Override
+ public void setFocus() {
+ queryField.setFocus();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.jcr;
+
+import java.util.List;
+
+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.cms.ui.jcr.DefaultRepositoryRegister;
+import org.argeo.cms.ui.jcr.JcrBrowserUtils;
+import org.argeo.cms.ui.jcr.JcrDClickListener;
+import org.argeo.cms.ui.jcr.NodeContentProvider;
+import org.argeo.cms.ui.jcr.NodeLabelProvider;
+import org.argeo.cms.ui.jcr.PropertiesContentProvider;
+import org.argeo.cms.ui.jcr.RepositoryRegister;
+import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
+import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
+import org.argeo.node.security.Keyring;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.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.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Basic View to display a sash form to browse a JCR compliant multiple
+ * repository environment
+ */
+public class JcrBrowserView extends ViewPart {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".jcrBrowserView";
+ private boolean sortChildNodes = true;
+
+ /* DEPENDENCY INJECTION */
+ private Keyring keyring;
+ private RepositoryRegister repositoryRegister = new DefaultRepositoryRegister();
+ private RepositoryFactory repositoryFactory;
+ private Repository nodeRepository;
+
+ // Current user session on the "Argeo node" default workspace
+ private Session userSession;
+
+ // This page widgets
+ private TreeViewer nodesViewer;
+ private NodeContentProvider nodeContentProvider;
+ private TableViewer propertiesViewer;
+ private EventListener resultsObserver;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ parent.setLayout(new FillLayout());
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
+ sashForm.setSashWidth(4);
+ sashForm.setLayout(new FillLayout());
+
+ // Create the tree on top of the view
+ Composite top = new Composite(sashForm, SWT.NONE);
+ GridLayout gl = new GridLayout(1, false);
+ top.setLayout(gl);
+
+ try {
+ this.userSession = this.nodeRepository.login();
+ } catch (RepositoryException e) {
+ throw new EclipseUiException("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);
+ getSite().registerContextMenu(menuManager, nodesViewer);
+ getSite().setSelectionProvider(nodesViewer);
+
+ nodesViewer.setInput(getViewSite());
+
+ // Create the property viewer on the bottom
+ Composite bottom = new Composite(sashForm, SWT.NONE);
+ bottom.setLayout(new GridLayout(1, false));
+ propertiesViewer = createPropertiesViewer(bottom);
+
+ sashForm.setWeights(getWeights());
+ nodesViewer.setComparer(new NodeViewerComparer());
+ }
+
+ 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(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(getViewSite());
+ }
+ }
+ });
+
+ 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);
+ 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 "<binary>";
+ 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(getViewSite());
+ return propertiesViewer;
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ }
+
+ 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(getViewSite());
+ }
+
+ /** 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<Event> 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<Event> events) throws RepositoryException {
+ if (getLog().isTraceEnabled())
+ getLog().trace("Refresh result list");
+ nodesViewer.refresh();
+ }
+
+ }
+
+ public boolean getSortChildNodes() {
+ return sortChildNodes;
+ }
+
+ @Override
+ public void setFocus() {
+ getNodeViewer().getTree().setFocus();
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
+ this.repositoryRegister = repositoryRegister;
+ }
+
+ public void setKeyring(Keyring keyring) {
+ this.keyring = keyring;
+ }
+
+ public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+ this.repositoryFactory = repositoryFactory;
+ }
+
+ public void setNodeRepository(Repository nodeRepository) {
+ this.nodeRepository = nodeRepository;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.jcr;
+
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.spi.FileSystemProvider;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.fs.SimpleFsBrowser;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+
+/** Browse the node file system. */
+public class NodeFsBrowserView extends ViewPart {
+ public final static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".nodeFsBrowserView";
+
+ private FileSystemProvider nodeFileSystemProvider;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ try {
+ URI uri = new URI("node:///");
+ FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri);
+ if (fileSystem == null)
+ fileSystem = nodeFileSystemProvider.newFileSystem(uri, null);
+ Path nodePath = fileSystem.getPath("~");
+ SimpleFsBrowser browser = new SimpleFsBrowser(parent, SWT.NO_FOCUS);
+ browser.setInput(nodePath);
+ } catch (Exception e) {
+ throw new CmsException("Cannot open file system browser", e);
+ }
+ }
+
+ @Override
+ public void setFocus() {
+ }
+
+ public void setNodeFileSystemProvider(FileSystemProvider nodeFileSystemProvider) {
+ this.nodeFileSystemProvider = nodeFileSystemProvider;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.jcr;
+
+import static javax.jcr.Node.JCR_CONTENT;
+import static javax.jcr.Property.JCR_DATA;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.cms.ui.jcr.JcrDClickListener;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.cms.ui.workbench.internal.jcr.parts.GenericNodeEditorInput;
+import org.argeo.cms.ui.workbench.util.CommandUtils;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.specific.OpenFile;
+import org.argeo.eclipse.ui.specific.SingleSourcingException;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class WorkbenchJcrDClickListener extends JcrDClickListener {
+
+ public WorkbenchJcrDClickListener(TreeViewer nodeViewer) {
+ super(nodeViewer);
+ }
+
+ @Override
+ protected void openNode(Node node) {
+ try {
+ if (node.isNodeType(NodeType.NT_FILE)) {
+ // Also open it
+
+ String name = node.getName();
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(OpenFile.PARAM_FILE_NAME, name);
+
+ // TODO rather directly transmit the path to the node, once
+ // we have defined convention to provide an Absolute URI to
+ // a node in a multi repo / workspace / user context
+ // params.put(OpenFile.PARAM_FILE_URI,
+ // OpenFileService.JCR_SCHEME + node.getPath());
+
+ // we copy the node to a tmp file to be opened as a dirty
+ // workaround
+ File tmpFile = null;
+ // OutputStream os = null;
+ // InputStream is = null;
+ int i = name.lastIndexOf('.');
+ String prefix, suffix;
+ if (i == -1) {
+ prefix = name;
+ suffix = null;
+ } else {
+ prefix = name.substring(0, i);
+ suffix = name.substring(i);
+ }
+ Binary binary = null;
+ try {
+ tmpFile = File.createTempFile(prefix, suffix);
+ tmpFile.deleteOnExit();
+ } catch (IOException e1) {
+ throw new EclipseUiException("Cannot create temp file", e1);
+ }
+ try (OutputStream os = new FileOutputStream(tmpFile)) {
+ binary = node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
+ try (InputStream is = binary.getStream();) {
+ IOUtils.copy(is, os);
+ }
+ } catch (IOException e) {
+ throw new SingleSourcingException("Cannot open file " + prefix + "." + suffix, e);
+ } finally {
+ // IOUtils.closeQuietly(is);
+ // IOUtils.closeQuietly(os);
+ JcrUtils.closeQuietly(binary);
+ }
+ Path path = Paths.get(tmpFile.getAbsolutePath());
+ String uri = path.toUri().toString();
+ params.put(OpenFile.PARAM_FILE_URI, uri);
+ CommandUtils.callCommand(OpenFile.ID, params);
+ }
+ GenericNodeEditorInput gnei = new GenericNodeEditorInput(node);
+ WorkbenchUiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().openEditor(gnei,
+ DefaultNodeEditor.ID);
+ } catch (RepositoryException re) {
+ throw new EclipseUiException("Repository error while getting node info", re);
+ } catch (Exception pie) {
+ throw new EclipseUiException("Unexpected exception while opening node editor", pie);
+ }
+ }
+}
--- /dev/null
+## English labels for Agreo JCR UI application
+
+## Generic labels
+
+## Errors & warnings
+errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node
+warningInvalidNodeToImport=Can only import to a node
+warningInvalidMultipleSelection=This functionality is implemented only on a single node for the time being.
+warningUnversionableNode= Current node is not versionable.
+warningNoChildNode= Current node has no child.
+
+## Commands
+getNodeSizeCmdLbl= Get approx. size
+addFolderNodeCmdLbl= Add Folder
+
+## GenericNodeEditor
+nodeEditorLbl=Generic node editor
+genericNodePageTitle=Properties
+childNodesPageTitle=Children
+nodeRightsManagementPageTitle=Effective privileges
+nodeVersionHistoryPageTitle=History
+propertyEditorPageTitle=Properties Editor (Experimental)
+
+# History
+versionTreeSectionTitle=Version list
+versionHistorySectionTitle=History
+
+## Dummy ones
+testLbl=Internationalizations of messages seems to work properly.
--- /dev/null
+package org.argeo.cms.ui.workbench.osgi;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/** A tree element representing a {@link Bundle} */
+class BundleNode extends TreeParent {
+ private final Bundle bundle;
+
+ public BundleNode(Bundle bundle) {
+ this(bundle, false);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public BundleNode(Bundle bundle, boolean hasChildren) {
+ super(bundle.getSymbolicName());
+ this.bundle = bundle;
+
+ if (hasChildren) {
+ // REFERENCES
+ ServiceReference[] usedServices = bundle.getServicesInUse();
+ if (usedServices != null) {
+ for (ServiceReference sr : usedServices) {
+ if (sr != null)
+ addChild(new ServiceReferenceNode(sr, false));
+ }
+ }
+
+ // SERVICES
+ ServiceReference[] registeredServices = bundle
+ .getRegisteredServices();
+ if (registeredServices != null) {
+ for (ServiceReference sr : registeredServices) {
+ if (sr != null)
+ addChild(new ServiceReferenceNode(sr, true));
+ }
+ }
+ }
+
+ }
+
+ Bundle getBundle() {
+ return bundle;
+ }
+}
--- /dev/null
+//package org.argeo.eclipse.ui.workbench.osgi;
+//public class BundlesView {}
+
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.osgi;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.ColumnViewerComparator;
+import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Overview of the bundles as a table. Equivalent to Equinox 'ss' console
+ * command.
+ */
+public class BundlesView extends ViewPart {
+ private TableViewer viewer;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new TableViewer(parent);
+ viewer.setContentProvider(new BundleContentProvider());
+ viewer.getTable().setHeaderVisible(true);
+
+ EclipseUiSpecificUtils.enableToolTipSupport(viewer);
+
+ // ID
+ TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(30);
+ column.getColumn().setText("ID");
+ column.getColumn().setAlignment(SWT.RIGHT);
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -3122136344359358605L;
+
+ public String getText(Object element) {
+ return Long.toString(((Bundle) element).getBundleId());
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // State
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(18);
+ column.getColumn().setText("State");
+ column.setLabelProvider(new StateLabelProvider());
+ new ColumnViewerComparator(column);
+
+ // Symbolic name
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(250);
+ column.getColumn().setText("Symbolic Name");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -4280840684440451080L;
+
+ public String getText(Object element) {
+ return ((Bundle) element).getSymbolicName();
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // Version
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(150);
+ column.getColumn().setText("Version");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = 6871926308708629989L;
+
+ public String getText(Object element) {
+ Bundle bundle = (org.osgi.framework.Bundle) element;
+ return bundle.getVersion().toString();
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle().getBundleContext());
+
+ }
+
+ @Override
+ public void setFocus() {
+ if (viewer != null)
+ viewer.getControl().setFocus();
+ }
+
+ /** Content provider managing the array of bundles */
+ private static class BundleContentProvider implements IStructuredContentProvider {
+ private static final long serialVersionUID = -8533792785725875977L;
+
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof BundleContext) {
+ BundleContext bc = (BundleContext) inputElement;
+ return bc.getBundles();
+ }
+ return null;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+}
--- /dev/null
+//package org.argeo.eclipse.ui.workbench.osgi;
+//public class BundlesView {}
+
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.osgi;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.naming.ldap.LdapName;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.CmsSession;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.ColumnViewerComparator;
+import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
+import org.argeo.util.LangUtils;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Overview of the active CMS sessions.
+ */
+public class CmsSessionsView extends ViewPart {
+ private TableViewer viewer;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new TableViewer(parent);
+ viewer.setContentProvider(new CmsSessionContentProvider());
+ viewer.getTable().setHeaderVisible(true);
+
+ EclipseUiSpecificUtils.enableToolTipSupport(viewer);
+
+ int longColWidth = 150;
+ int smallColWidth = 100;
+
+ // Display name
+ TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(longColWidth);
+ column.getColumn().setText("User");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -5234573509093747505L;
+
+ public String getText(Object element) {
+ return ((CmsSession) element).getAuthorization().toString();
+ }
+
+ public String getToolTipText(Object element) {
+ return ((CmsSession) element).getUserDn().toString();
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // Creation time
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(smallColWidth);
+ column.getColumn().setText("Since");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -5234573509093747505L;
+
+ public String getText(Object element) {
+ return LangUtils.since(((CmsSession) element).getCreationTime());
+ }
+
+ public String getToolTipText(Object element) {
+ return ((CmsSession) element).getCreationTime().toString();
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // Username
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(smallColWidth);
+ column.getColumn().setText("Username");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -5234573509093747505L;
+
+ public String getText(Object element) {
+ LdapName userDn = ((CmsSession) element).getUserDn();
+ return userDn.getRdn(userDn.size() - 1).getValue().toString();
+ }
+
+ public String getToolTipText(Object element) {
+ return ((CmsSession) element).getUserDn().toString();
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // UUID
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(smallColWidth);
+ column.getColumn().setText("UUID");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -5234573509093747505L;
+
+ public String getText(Object element) {
+ return ((CmsSession) element).getUuid().toString();
+ }
+
+ public String getToolTipText(Object element) {
+ return getText(element);
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ // Local ID
+ column = new TableViewerColumn(viewer, SWT.NONE);
+ column.getColumn().setWidth(smallColWidth);
+ column.getColumn().setText("Local ID");
+ column.setLabelProvider(new ColumnLabelProvider() {
+ private static final long serialVersionUID = -5234573509093747505L;
+
+ public String getText(Object element) {
+ return ((CmsSession) element).getLocalId();
+ }
+
+ public String getToolTipText(Object element) {
+ return getText(element);
+ }
+ });
+ new ColumnViewerComparator(column);
+
+ viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle().getBundleContext());
+
+ }
+
+ @Override
+ public void setFocus() {
+ if (viewer != null)
+ viewer.getControl().setFocus();
+ }
+
+ /** Content provider managing the array of bundles */
+ private static class CmsSessionContentProvider implements IStructuredContentProvider {
+ private static final long serialVersionUID = -8533792785725875977L;
+
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof BundleContext) {
+ BundleContext bc = (BundleContext) inputElement;
+ Collection<ServiceReference<CmsSession>> srs;
+ try {
+ srs = bc.getServiceReferences(CmsSession.class, null);
+ } catch (InvalidSyntaxException e) {
+ throw new CmsException("Cannot retrieve CMS sessions", e);
+ }
+ List<CmsSession> res = new ArrayList<>();
+ for (ServiceReference<CmsSession> sr : srs) {
+ res.add(bc.getService(sr));
+ }
+ return res.toArray();
+ }
+ return null;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.osgi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.TreeParent;
+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.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/** The OSGi runtime from a module perspective. */
+public class ModulesView extends ViewPart {
+ private TreeViewer viewer;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ viewer.setContentProvider(new ModulesContentProvider());
+ viewer.setLabelProvider(new ModulesLabelProvider());
+ viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle()
+ .getBundleContext());
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTree().setFocus();
+ }
+
+ private class ModulesContentProvider implements ITreeContentProvider {
+ private static final long serialVersionUID = 3819934804640641721L;
+
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof BundleContext) {
+ BundleContext bundleContext = (BundleContext) parentElement;
+ Bundle[] bundles = bundleContext.getBundles();
+
+ List<BundleNode> modules = new ArrayList<BundleNode>();
+ for (Bundle bundle : bundles) {
+ if (bundle.getState() == Bundle.ACTIVE)
+ modules.add(new BundleNode(bundle, true));
+ }
+ return modules.toArray();
+ } else if (parentElement instanceof TreeParent) {
+ return ((TreeParent) parentElement).getChildren();
+ } else {
+ return null;
+ }
+ }
+
+ public Object getParent(Object element) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean hasChildren(Object element) {
+ if (element instanceof TreeParent) {
+ return ((TreeParent) element).hasChildren();
+ }
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ private class ModulesLabelProvider extends StateLabelProvider {
+ private static final long serialVersionUID = 5290046145534824722L;
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof BundleNode)
+ return element.toString() + " ["
+ + ((BundleNode) element).getBundle().getBundleId()
+ + "]";
+ return element.toString();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.osgi;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.TreeParent;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/** <b>Experimental</b> The OSGi runtime from a module perspective. */
+@SuppressWarnings({ "deprecation", "rawtypes", "unchecked" })
+public class MultiplePackagesView extends ViewPart {
+ private TreeViewer viewer;
+ private PackageAdmin packageAdmin;
+ private Comparator<ExportedPackage> epc = new Comparator<ExportedPackage>() {
+ public int compare(ExportedPackage o1, ExportedPackage o2) {
+ if (!o1.getName().equals(o2.getName()))
+ return o1.getName().compareTo(o2.getName());
+ else
+ return o1.getVersion().compareTo(o2.getVersion());
+ }
+ };
+
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ viewer.setContentProvider(new ModulesContentProvider());
+ viewer.setLabelProvider(new LabelProvider());
+ viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle()
+ .getBundleContext());
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTree().setFocus();
+ }
+
+ private class ModulesContentProvider implements ITreeContentProvider {
+ private static final long serialVersionUID = 3819934804640641721L;
+
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof BundleContext) {
+ BundleContext bundleContext = (BundleContext) parentElement;
+ Bundle[] bundles = bundleContext.getBundles();
+
+ // scan packages
+ ServiceReference paSr = bundleContext
+ .getServiceReference(PackageAdmin.class.getName());
+ // TODO: make a cleaner referencing
+ packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
+
+ Map<Bundle, Set<ExportedPackage>> imported = new HashMap<Bundle, Set<ExportedPackage>>();
+ Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
+ for (Bundle bundle : bundles) {
+ processBundle(bundle, imported, packages);
+ }
+
+ List<MultiplePackagesNode> multiplePackages = new ArrayList<MultiplePackagesNode>();
+ for (String packageName : packages.keySet()) {
+ Set<ExportedPackage> pkgs = packages.get(packageName);
+ if (pkgs.size() > 1) {
+ MultiplePackagesNode mpn = new MultiplePackagesNode(
+ packageName, pkgs);
+ multiplePackages.add(mpn);
+ }
+ }
+
+ return multiplePackages.toArray();
+ } else if (parentElement instanceof TreeParent) {
+ return ((TreeParent) parentElement).getChildren();
+ } else {
+ return null;
+ }
+ }
+
+ protected void processBundle(Bundle bundle,
+ Map<Bundle, Set<ExportedPackage>> imported,
+ Map<String, Set<ExportedPackage>> packages) {
+ ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle);
+ if (pkgs == null)
+ return;
+ for (ExportedPackage pkg : pkgs) {
+ if (!packages.containsKey(pkg.getName()))
+ packages.put(pkg.getName(), new TreeSet<ExportedPackage>(
+ epc));
+ Set<ExportedPackage> expPackages = packages.get(pkg.getName());
+ expPackages.add(pkg);
+
+ // imported
+ for (Bundle b : pkg.getImportingBundles()) {
+ if (bundle.getBundleId() != b.getBundleId()) {
+ if (!imported.containsKey(b)) {
+ imported.put(b, new TreeSet<ExportedPackage>(epc));
+ }
+ Set<ExportedPackage> impPackages = imported.get(b);
+ impPackages.add(pkg);
+ }
+ }
+ }
+ }
+
+ public Object getParent(Object element) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean hasChildren(Object element) {
+ if (element instanceof TreeParent) {
+ return ((TreeParent) element).hasChildren();
+ }
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ private class MultiplePackagesNode extends TreeParent {
+ public MultiplePackagesNode(String packageName,
+ Set<ExportedPackage> exportedPackages) {
+ super(packageName);
+ for (ExportedPackage pkg : exportedPackages) {
+ addChild(new ExportedPackageNode(pkg));
+ }
+ }
+ }
+
+ private class ExportedPackageNode extends TreeParent {
+ public ExportedPackageNode(ExportedPackage exportedPackage) {
+ super(exportedPackage.getName() + " - "
+ + exportedPackage.getVersion() + " ("
+ + exportedPackage.getExportingBundle() + ")");
+ for (Bundle bundle : exportedPackage.getImportingBundles()) {
+ addChild(new BundleNode(bundle, true));
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.osgi;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.eclipse.swt.graphics.Image;
+
+/** Shared icons. */
+public class OsgiExplorerImages {
+ public final static Image INSTALLED = WorkbenchUiPlugin.getImageDescriptor(
+ "icons/installed.gif").createImage();
+ public final static Image RESOLVED = WorkbenchUiPlugin.getImageDescriptor(
+ "icons/resolved.gif").createImage();
+ public final static Image STARTING = WorkbenchUiPlugin.getImageDescriptor(
+ "icons/starting.gif").createImage();
+ public final static Image ACTIVE = WorkbenchUiPlugin.getImageDescriptor(
+ "icons/active.gif").createImage();
+ public final static Image SERVICE_PUBLISHED = WorkbenchUiPlugin
+ .getImageDescriptor("icons/service_published.gif").createImage();
+ public final static Image SERVICE_REFERENCED = WorkbenchUiPlugin
+ .getImageDescriptor("icons/service_referenced.gif").createImage();
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.osgi;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/** A tree element representing a {@link ServiceReference} */
+@SuppressWarnings({ "rawtypes" })
+class ServiceReferenceNode extends TreeParent {
+ private final ServiceReference serviceReference;
+ private final boolean published;
+
+ public ServiceReferenceNode(ServiceReference serviceReference,
+ boolean published) {
+ super(serviceReference.toString());
+ this.serviceReference = serviceReference;
+ this.published = published;
+
+ if (isPublished()) {
+ Bundle[] usedBundles = serviceReference.getUsingBundles();
+ if (usedBundles != null) {
+ for (Bundle b : usedBundles) {
+ if (b != null)
+ addChild(new BundleNode(b));
+ }
+ }
+ } else {
+ Bundle provider = serviceReference.getBundle();
+ addChild(new BundleNode(provider));
+ }
+
+ for (String key : serviceReference.getPropertyKeys()) {
+ addChild(new TreeParent(key + "="
+ + serviceReference.getProperty(key)));
+ }
+
+ }
+
+ public ServiceReference getServiceReference() {
+ return serviceReference;
+ }
+
+ public boolean isPublished() {
+ return published;
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.osgi;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/** Label provider showing the sate of bundles */
+class StateLabelProvider extends ColumnLabelProvider {
+ private static final long serialVersionUID = -7885583135316000733L;
+
+ @Override
+ public Image getImage(Object element) {
+ int state;
+ if (element instanceof Bundle)
+ state = ((Bundle) element).getState();
+ else if (element instanceof BundleNode)
+ state = ((BundleNode) element).getBundle().getState();
+ else if (element instanceof ServiceReferenceNode)
+ if (((ServiceReferenceNode) element).isPublished())
+ return OsgiExplorerImages.SERVICE_PUBLISHED;
+ else
+ return OsgiExplorerImages.SERVICE_REFERENCED;
+ else
+ return null;
+
+ switch (state) {
+ case Bundle.UNINSTALLED:
+ return OsgiExplorerImages.INSTALLED;
+ case Bundle.INSTALLED:
+ return OsgiExplorerImages.INSTALLED;
+ case Bundle.RESOLVED:
+ return OsgiExplorerImages.RESOLVED;
+ case Bundle.STARTING:
+ return OsgiExplorerImages.STARTING;
+ case Bundle.STOPPING:
+ return OsgiExplorerImages.STARTING;
+ case Bundle.ACTIVE:
+ return OsgiExplorerImages.ACTIVE;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public String getText(Object element) {
+ return null;
+ }
+
+ @Override
+ public String getToolTipText(Object element) {
+ Bundle bundle = (Bundle) element;
+ Integer state = bundle.getState();
+ switch (state) {
+ case Bundle.UNINSTALLED:
+ return "UNINSTALLED";
+ case Bundle.INSTALLED:
+ return "INSTALLED";
+ case Bundle.RESOLVED:
+ return "RESOLVED";
+ case Bundle.STARTING:
+ String activationPolicy = bundle.getHeaders()
+ .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
+
+ // .get("Bundle-ActivationPolicy").toString();
+ // FIXME constant triggers the compilation failure
+ if (activationPolicy != null
+ && activationPolicy.equals(Constants.ACTIVATION_LAZY))
+ // && activationPolicy.equals("lazy"))
+ // FIXME constant triggers the compilation failure
+ // && activationPolicy.equals(Constants.ACTIVATION_LAZY))
+ return "<<LAZY>>";
+ return "STARTING";
+ case Bundle.STOPPING:
+ return "STOPPING";
+ case Bundle.ACTIVE:
+ return "ACTIVE";
+ default:
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.useradmin;
+
+import java.util.ArrayList;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.node.ArgeoLogger;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Display log lines for all users with a virtual table.
+ */
+public class AdminLogView extends ViewPart {
+ public static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".adminLogView";
+
+ private TableViewer viewer;
+
+ private LogContentProvider logContentProvider;
+ private ArgeoLogger argeoLogger;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ // FIXME doesn't return a monospace font in RAP
+ Font font = JFaceResources.getTextFont();
+ Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+ table.setFont(font);
+
+ viewer = new TableViewer(table);
+ viewer.setLabelProvider(new LabelProvider());
+ logContentProvider = new LogContentProvider(viewer) {
+ private static final long serialVersionUID = -3401776448301180724L;
+
+ @Override
+ protected StringBuffer prefix(String username, Long timestamp,
+ String level, String category, String thread) {
+ return super
+ .prefix(username, timestamp, level, category, thread)
+ .append(norm(level, 5))
+ .append(' ')
+ .append(norm(username != null ? username
+ : "<anonymous>", 16)).append(' ');
+ }
+ };
+ viewer.setContentProvider(logContentProvider);
+ // viewer.setUseHashlookup(true);
+ viewer.setInput(new ArrayList<String>());
+
+ if (argeoLogger != null)
+ argeoLogger.registerForAll(logContentProvider, 1000, true);
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTable().setFocus();
+ }
+
+ @Override
+ public void dispose() {
+ if (argeoLogger != null)
+ argeoLogger.unregisterForAll(logContentProvider);
+ }
+
+ public void setArgeoLogger(ArgeoLogger argeoLogger) {
+ this.argeoLogger = argeoLogger;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.useradmin;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.argeo.node.ArgeoLogListener;
+import org.eclipse.jface.viewers.ILazyContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+/** A content provider maintaining an array of lines */
+class LogContentProvider implements ILazyContentProvider, ArgeoLogListener {
+ private static final long serialVersionUID = -2084872367738339721L;
+
+ private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+ private final Long start;
+ /** current - start = line number. first line is number '1' */
+ private Long current;
+
+ // TODO make it configurable
+ private final Integer maxLineBufferSize = 10 * 1000;
+
+ private final TableViewer viewer;
+ private LinkedList<LogLine> lines;
+
+ public LogContentProvider(TableViewer viewer) {
+ this.viewer = viewer;
+ start = System.currentTimeMillis();
+ lines = new LinkedList<LogLine>();
+ current = start;
+ }
+
+ public synchronized void dispose() {
+ lines.clear();
+ lines = null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ List<String> lin = (List<String>) newInput;
+ if (lin == null)
+ return;
+ for (String line : lin) {
+ addLine(line);
+ }
+ this.viewer.setItemCount(lines.size());
+ }
+
+ public void updateElement(int index) {
+ viewer.replace(lines.get(index), index);
+ }
+
+ public synchronized void appendLog(String username, Long timestamp,
+ String level, String category, String thread, Object msg,
+ String[] exception) {
+ // check if valid
+ if (lines == null)
+ return;
+
+ String message = msg.toString();
+ int count = 0;
+ String prefix = prefix(username, timestamp, level, category, thread)
+ .toString();
+ // String suffix = suffix(username, timestamp, level, category, thread);
+ for (String line : message.split("\n")) {
+ addLine(count == 0 ? prefix + line : line);
+ count++;
+ }
+
+ if (exception != null) {
+ for (String ste : exception) {
+ addLine(ste);
+ }
+ }
+
+ viewer.getTable().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (lines == null)
+ return;
+ viewer.setItemCount(lines.size());
+ // doesn't work with syncExec
+ scrollToLastLine();
+ }
+ });
+ }
+
+ protected StringBuffer prefix(String username, Long timestamp,
+ String level, String category, String thread) {
+ StringBuffer buf = new StringBuffer("");
+ buf.append(dateFormat.format(new Date(timestamp))).append(" ");
+ // buf.append(level).append(" ");
+ return buf;
+ }
+
+ /** Normalize string to the given size */
+ protected String norm(String str, Integer size) {
+ int length = str.length();
+ if (length == size)
+ return str;
+ else if (length > size)
+ return str.substring(0, size);
+ else {
+ char[] arr = new char[size - length];
+ Arrays.fill(arr, ' ');
+ return str + new String(arr);
+ }
+ }
+
+ // protected String suffix(String username, Long timestamp, String level,
+ // String category, String thread) {
+ // return "";
+ // }
+
+ /** Scroll to the last line */
+ protected synchronized void scrollToLastLine() {
+ // we try to show last line with two methods
+ // viewer.reveal(lines.peekLast());
+
+ Table table = viewer.getTable();
+ TableItem ti = table.getItem(table.getItemCount() - 1);
+ table.showItem(ti);
+ }
+
+ protected synchronized LogLine addLine(String line) {
+ // check for maximal size and purge if necessary
+ while (lines.size() >= maxLineBufferSize) {
+ for (int i = 0; i < maxLineBufferSize / 10; i++) {
+ lines.poll();
+ }
+ }
+
+ current++;
+ LogLine logLine = new LogLine(current, line);
+ lines.add(logLine);
+ return logLine;
+ }
+
+ private class LogLine {
+ private Long linenumber;
+ private String message;
+
+ public LogLine(Long linenumber, String message) {
+ this.linenumber = linenumber;
+ this.message = message;
+ }
+
+ @Override
+ public int hashCode() {
+ return linenumber.intValue();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LogLine)
+ return ((LogLine) obj).linenumber.equals(linenumber);
+ else
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return message;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.useradmin;
+
+import java.util.ArrayList;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.node.ArgeoLogListener;
+import org.argeo.node.ArgeoLogger;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Display log lines with a virtual table. Register and unregisters a
+ * {@link ArgeoLogListener} via OSGi services.
+ */
+public class LogView extends ViewPart {
+ public static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".logView";
+
+ private TableViewer viewer;
+
+ private LogContentProvider logContentProvider;
+ private ArgeoLogger argeoLogger;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ Font font = JFaceResources.getTextFont();
+ Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+ table.setFont(font);
+
+ viewer = new TableViewer(table);
+ viewer.setLabelProvider(new LabelProvider());
+ logContentProvider = new LogContentProvider(viewer);
+ viewer.setContentProvider(logContentProvider);
+ // viewer.setUseHashlookup(true);
+ viewer.setInput(new ArrayList<String>());
+
+ if (argeoLogger != null)
+ argeoLogger.register(logContentProvider, 1000);
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTable().setFocus();
+ }
+
+ @Override
+ public void dispose() {
+ if (argeoLogger != null)
+ argeoLogger.unregister(logContentProvider);
+ }
+
+ public void setArgeoLogger(ArgeoLogger argeoLogger) {
+ this.argeoLogger = argeoLogger;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.useradmin;
+
+import java.util.TreeSet;
+
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+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.Table;
+import org.eclipse.ui.part.ViewPart;
+
+/** Information about the currently logged in user */
+public class UserProfile extends ViewPart {
+ public static String ID = WorkbenchUiPlugin.PLUGIN_ID + ".userProfile";
+
+ private TableViewer viewer;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ parent.setLayout(new GridLayout(2, false));
+
+ // Authentication authentication = CurrentUser.getAuthentication();
+ // EclipseUiUtils.createGridLL(parent, "Name", authentication
+ // .getPrincipal().toString());
+ EclipseUiUtils.createGridLL(parent, "User ID",
+ CurrentUser.getUsername());
+
+ // roles table
+ Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER);
+ table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+ table.setLinesVisible(false);
+ table.setHeaderVisible(false);
+ viewer = new TableViewer(table);
+ viewer.setContentProvider(new RolesContentProvider());
+ viewer.setLabelProvider(new LabelProvider());
+ getViewSite().setSelectionProvider(viewer);
+ viewer.setInput(getViewSite());
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTable();
+ }
+
+ private class RolesContentProvider implements IStructuredContentProvider {
+ private static final long serialVersionUID = -4576917440167866233L;
+
+ public Object[] getElements(Object inputElement) {
+ return new TreeSet<String>(CurrentUser.roles()).toArray();
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.Parameterization;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.menus.CommandContributionItem;
+import org.eclipse.ui.menus.CommandContributionItemParameter;
+import org.eclipse.ui.services.IServiceLocator;
+
+/**
+ * Centralises useful and generic methods when dealing with commands in an
+ * Eclipse Workbench context
+ */
+public class CommandUtils {
+
+ /**
+ * Commodities the refresh of a single command with no parameter in a
+ * Menu.aboutToShow method to simplify further development
+ *
+ * Note: that this method should be called with a false show command flag to
+ * remove a contribution that have been previously contributed
+ */
+ public static void refreshCommand(IMenuManager menuManager, IServiceLocator locator, String cmdId, String label,
+ ImageDescriptor icon, boolean showCommand) {
+ refreshParameterizedCommand(menuManager, locator, cmdId, label, icon, showCommand, null);
+ }
+
+ /**
+ * Commodities the refresh the contribution of a command with a map of
+ * parameters in a context menu
+ *
+ * The command ID is used has contribution item ID
+ */
+ public static void refreshParameterizedCommand(IMenuManager menuManager, IServiceLocator locator, String cmdId,
+ String label, ImageDescriptor icon, boolean showCommand, Map<String, String> params) {
+ refreshParameterizedCommand(menuManager, locator, cmdId, cmdId, label, icon, showCommand, params);
+ }
+
+ /**
+ * Commodities the refresh the contribution of a command with a map of
+ * parameters in a context menu
+ *
+ * @param menuManager
+ * @param locator
+ * @param contributionId
+ * @param commandId
+ * @param label
+ * @param icon
+ * @param showCommand
+ * @param params
+ */
+ public static void refreshParameterizedCommand(IMenuManager menuManager, IServiceLocator locator,
+ String contributionId, String commandId, String label, ImageDescriptor icon, boolean showCommand,
+ Map<String, String> params) {
+ IContributionItem ici = menuManager.find(contributionId);
+ if (ici != null)
+ menuManager.remove(ici);
+ if (showCommand) {
+ CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter(locator,
+ null, commandId, SWT.PUSH);
+
+ // Set Params
+ contributionItemParameter.label = label;
+ contributionItemParameter.icon = icon;
+
+ if (params != null)
+ contributionItemParameter.parameters = params;
+
+ CommandContributionItem cci = new CommandContributionItem(contributionItemParameter);
+ cci.setId(contributionId);
+ menuManager.add(cci);
+ }
+ }
+
+ /** Helper to call a command without parameter easily */
+ public static void callCommand(String commandID) {
+ callCommand(commandID, null);
+ }
+
+ /** Helper to call a command with a single parameter easily */
+ public static void callCommand(String commandID, String parameterID, String parameterValue) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(parameterID, parameterValue);
+ callCommand(commandID, params);
+ }
+
+ /**
+ * Helper to call a command with a map of parameters easily
+ *
+ * @param paramMap
+ * a map that links various command IDs with corresponding String
+ * values.
+ */
+ public static void callCommand(String commandID, Map<String, String> paramMap) {
+ try {
+ IWorkbench iw = WorkbenchUiPlugin.getDefault().getWorkbench();
+ IHandlerService handlerService = (IHandlerService) iw.getService(IHandlerService.class);
+ ICommandService cmdService = (ICommandService) iw.getActiveWorkbenchWindow()
+ .getService(ICommandService.class);
+ Command cmd = cmdService.getCommand(commandID);
+
+ ArrayList<Parameterization> parameters = null;
+ ParameterizedCommand pc;
+
+ if (paramMap != null) {
+ // Set parameters of the command to launch :
+ parameters = new ArrayList<Parameterization>();
+ Parameterization parameterization;
+
+ for (String id : paramMap.keySet()) {
+ parameterization = new Parameterization(cmd.getParameter(id), paramMap.get(id));
+ parameters.add(parameterization);
+ }
+ pc = new ParameterizedCommand(cmd, parameters.toArray(new Parameterization[parameters.size()]));
+ } else
+ pc = new ParameterizedCommand(cmd, null);
+
+ // execute the command
+ handlerService.executeCommand(pc, null);
+ } catch (Exception e) {
+ throw new EclipseUiException("Unexpected error while" + " calling the command " + commandID, e);
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.ui.workbench.util;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * Propagate authentication to an eclipse job. Typically to execute a privileged
+ * action outside the UI thread
+ */
+public abstract class PrivilegedJob extends Job {
+ private final Subject subject;
+
+ public PrivilegedJob(String jobName) {
+ this(jobName, AccessController.getContext());
+ }
+
+ public PrivilegedJob(String jobName,
+ AccessControlContext accessControlContext) {
+ super(jobName);
+ subject = Subject.getSubject(accessControlContext);
+
+ // Must be called *before* the job is scheduled,
+ // it is required for the progress window to appear
+ setUser(true);
+ }
+
+ @Override
+ protected IStatus run(final IProgressMonitor progressMonitor) {
+ PrivilegedAction<IStatus> privilegedAction = new PrivilegedAction<IStatus>() {
+ public IStatus run() {
+ return doRun(progressMonitor);
+ }
+ };
+ return Subject.doAs(subject, privilegedAction);
+ }
+
+ /**
+ * Implement here what should be executed with default context
+ * authentication
+ */
+ protected abstract IStatus doRun(IProgressMonitor progressMonitor);
+}
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.ui.workbench.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.argeo.cms.auth.CurrentUser;
+import org.eclipse.ui.AbstractSourceProvider;
+
+/**
+ * Provides the roles of the current user as a variable to be used for activity
+ * binding
+ */
+public class RolesSourceProvider extends AbstractSourceProvider {
+ public final static String ROLES_VARIABLE = "roles";
+ private final static String[] PROVIDED_SOURCE_NAMES = new String[] { ROLES_VARIABLE };
+
+ public Map<String, Set<String>> getCurrentState() {
+ Map<String, Set<String>> stateMap = new HashMap<String, Set<String>>();
+ stateMap.put(ROLES_VARIABLE, CurrentUser.roles());
+ return stateMap;
+ }
+
+ public String[] getProvidedSourceNames() {
+ return PROVIDED_SOURCE_NAMES;
+ }
+
+ public void updateRoles() {
+ fireSourceChanged(0, getCurrentState());
+ }
+
+ public void dispose() {
+ }
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.eclipse.spring;\r
+\r
+import static java.text.MessageFormat.format;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.osgi.framework.Bundle;\r
+import org.osgi.framework.BundleContext;\r
+import org.osgi.framework.BundleException;\r
+import org.osgi.framework.FrameworkUtil;\r
+import org.osgi.framework.InvalidSyntaxException;\r
+import org.osgi.util.tracker.ServiceTracker;\r
+import org.springframework.context.ApplicationContext;\r
+\r
+/**\r
+ * Tracks Spring application context published as services.\r
+ * \r
+ * @author Heiko Seeberger\r
+ * @author Mathieu Baudier\r
+ */\r
+class ApplicationContextTracker {\r
+ private final static Log log = LogFactory\r
+ .getLog(ApplicationContextTracker.class);\r
+\r
+ private static final String FILTER = "(&(objectClass=org.springframework.context.ApplicationContext)" //$NON-NLS-1$\r
+ + "(org.springframework.context.service.name={0}))"; //$NON-NLS-1$\r
+\r
+ public final static String APPLICATION_CONTEXT_TRACKER_TIMEOUT = "org.argeo.eclipse.spring.applicationContextTrackerTimeout";\r
+\r
+ private static Long defaultTimeout = Long.parseLong(System.getProperty(\r
+ APPLICATION_CONTEXT_TRACKER_TIMEOUT, "30000"));\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ private ServiceTracker applicationContextServiceTracker;\r
+\r
+ /**\r
+ * @param contributorBundle\r
+ * OSGi bundle for which the Spring application context is to be\r
+ * tracked. Must not be null!\r
+ * @param factoryBundleContext\r
+ * BundleContext object which can be used to track services\r
+ * @throws IllegalArgumentException\r
+ * if the given bundle is null.\r
+ */\r
+ @SuppressWarnings({ "unchecked", "rawtypes" })\r
+ public ApplicationContextTracker(final Bundle contributorBundle,\r
+ final BundleContext factoryBundleContext) {\r
+ final String filter = format(FILTER,\r
+ contributorBundle.getSymbolicName());\r
+ try {\r
+ applicationContextServiceTracker = new ServiceTracker(\r
+ factoryBundleContext, FrameworkUtil.createFilter(filter),\r
+ null);\r
+ // applicationContextServiceTracker.open();\r
+ } catch (final InvalidSyntaxException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public void open() {\r
+ if (applicationContextServiceTracker != null) {\r
+ applicationContextServiceTracker.open();\r
+ }\r
+ }\r
+\r
+ public void close() {\r
+ if (applicationContextServiceTracker != null) {\r
+ applicationContextServiceTracker.close();\r
+ }\r
+ }\r
+\r
+ public ApplicationContext getApplicationContext() {\r
+ ApplicationContext applicationContext = null;\r
+ if (applicationContextServiceTracker != null) {\r
+ try {\r
+ applicationContext = (ApplicationContext) applicationContextServiceTracker\r
+ .waitForService(defaultTimeout);\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ return applicationContext;\r
+ }\r
+\r
+ @Override\r
+ protected void finalize() throws Throwable {\r
+ close();\r
+ super.finalize();\r
+ }\r
+\r
+ static ApplicationContext getApplicationContext(String bundleSymbolicName) {\r
+ Bundle contributorBundle = Platform.getBundle(bundleSymbolicName);\r
+ return getApplicationContext(contributorBundle);\r
+ }\r
+\r
+ static ApplicationContext getApplicationContext(\r
+ final Bundle contributorBundle) {\r
+ if (log.isTraceEnabled())\r
+ log.trace("Get application context for bundle " + contributorBundle);\r
+\r
+ // Start if not yet started (also if in STARTING state, may be lazy)\r
+ if (contributorBundle.getState() != Bundle.ACTIVE) {\r
+ if (log.isTraceEnabled())\r
+ log.trace("Starting bundle: "\r
+ + contributorBundle.getSymbolicName());\r
+ // Thread startBundle = new Thread("Start bundle "\r
+ // + contributorBundle.getSymbolicName()) {\r
+ // public void run() {\r
+ try {\r
+ contributorBundle.start();\r
+ } catch (BundleException e) {\r
+ log.error("Cannot start bundle " + contributorBundle, e);\r
+ }\r
+ // }\r
+ // };\r
+ // startBundle.start();\r
+ // try {\r
+ // startBundle.join(10 * 1000l);\r
+ // } catch (InterruptedException e) {\r
+ // // silent\r
+ // }\r
+ }\r
+\r
+ final ApplicationContextTracker applicationContextTracker = new ApplicationContextTracker(\r
+ contributorBundle, contributorBundle.getBundleContext());\r
+ ApplicationContext applicationContext = null;\r
+ try {\r
+ applicationContextTracker.open();\r
+ applicationContext = applicationContextTracker\r
+ .getApplicationContext();\r
+ } finally {\r
+ applicationContextTracker.close();\r
+ }\r
+ return applicationContext;\r
+ }\r
+}\r
--- /dev/null
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.eclipse.spring;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.springframework.context.ApplicationContext;
+
+/** Allows to declare Eclipse commands as Spring beans */
+public class SpringCommandHandler implements IHandler {
+ private final static Log log = LogFactory
+ .getLog(SpringCommandHandler.class);
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ }
+
+ public void dispose() {
+ }
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ String commandId = event.getCommand().getId();
+ String bundleSymbolicName = commandId.substring(0,
+ commandId.lastIndexOf('.'));
+ try {
+ if (log.isTraceEnabled())
+ log.trace("Execute " + event + " via spring command handler "
+ + this);
+ // TODO: make it more flexible and robust
+ ApplicationContext applicationContext = ApplicationContextTracker
+ .getApplicationContext(bundleSymbolicName);
+ if (applicationContext == null)
+ throw new EclipseUiException(
+ "No application context found for "
+ + bundleSymbolicName);
+
+ // retrieve the command via its id
+ String beanName = event.getCommand().getId();
+
+ if (!applicationContext.containsBean(beanName)) {
+ if (beanName.startsWith(bundleSymbolicName))
+ beanName = beanName
+ .substring(bundleSymbolicName.length() + 1);
+ }
+
+ if (!applicationContext.containsBean(beanName))
+ throw new ExecutionException("No bean found with name "
+ + beanName + " in bundle " + bundleSymbolicName);
+ Object bean = applicationContext.getBean(beanName);
+
+ if (!(bean instanceof IHandler))
+ throw new ExecutionException("Bean with name " + beanName
+ + " and class " + bean.getClass()
+ + " does not implement the IHandler interface.");
+
+ IHandler handler = (IHandler) bean;
+ return handler.execute(event);
+ } catch (Exception e) {
+ // TODO: use eclipse error management
+ // log.error(e);
+ throw new ExecutionException("Cannot execute Spring command "
+ + commandId + " in bundle " + bundleSymbolicName, e);
+ }
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ public boolean isHandled() {
+ return true;
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ }
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.eclipse.spring;\r
+\r
+import org.argeo.eclipse.ui.EclipseUiException;\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IConfigurationElement;\r
+import org.eclipse.core.runtime.IExecutableExtension;\r
+import org.eclipse.core.runtime.IExecutableExtensionFactory;\r
+import org.eclipse.core.runtime.IExtension;\r
+import org.springframework.context.ApplicationContext;\r
+\r
+/**\r
+ * The Spring Extension Factory builds a bridge between the Eclipse Extension\r
+ * Registry and the Spring Framework (especially Spring Dynamic Modules).\r
+ * \r
+ * It allows you to define your extension as a spring bean within the spring\r
+ * application context of your bundle. If you would like to use this bean as an\r
+ * instance of an extension (an Eclipse RCP view, for example) you define the\r
+ * extension with this spring extension factory as the class to be created.\r
+ * \r
+ * To let the spring extension factory pick the right bean from your application\r
+ * context you need to set the bean id to the same value as the id of the view\r
+ * within the view definition, for example. This is important if your extension\r
+ * definition contains more than one element, where each element has its own id.\r
+ * \r
+ * If the extension definition elements themselves have no id attribute the\r
+ * spring extension factory uses the id of the extension itself to identify the\r
+ * bean.\r
+ * \r
+ * original code from: <a href=\r
+ * "http://martinlippert.blogspot.com/2008/10/new-version-of-spring-extension-factory.html"\r
+ * >Blog entry</a>\r
+ * \r
+ * @author Martin Lippert\r
+ * @author mbaudier\r
+ */\r
+public class SpringExtensionFactory implements IExecutableExtensionFactory,\r
+ IExecutableExtension {\r
+\r
+ private Object bean;\r
+\r
+ public Object create() throws CoreException {\r
+ if (bean == null)\r
+ throw new EclipseUiException("No underlying bean for extension");\r
+ return bean;\r
+ }\r
+\r
+ public void setInitializationData(IConfigurationElement config,\r
+ String propertyName, Object data) throws CoreException {\r
+ String bundleSymbolicName = config.getContributor().getName();\r
+ ApplicationContext applicationContext = ApplicationContextTracker\r
+ .getApplicationContext(bundleSymbolicName);\r
+ if (applicationContext == null)\r
+ throw new EclipseUiException(\r
+ "Cannot find application context for bundle "\r
+ + bundleSymbolicName);\r
+\r
+ String beanName = getBeanName(data, config);\r
+ if (beanName == null)\r
+ throw new EclipseUiException("Cannot find bean name for extension "\r
+ + config);\r
+\r
+ if (!applicationContext.containsBean(beanName)) {\r
+ if (beanName.startsWith(bundleSymbolicName))\r
+ beanName = beanName.substring(bundleSymbolicName.length() + 1);\r
+ }\r
+\r
+ if (!applicationContext.containsBean(beanName))\r
+ throw new EclipseUiException("No bean with name '" + beanName + "'");\r
+\r
+ this.bean = applicationContext.getBean(beanName);\r
+ if (this.bean instanceof IExecutableExtension) {\r
+ ((IExecutableExtension) this.bean).setInitializationData(config,\r
+ propertyName, data);\r
+ }\r
+ }\r
+\r
+ private String getBeanName(Object data, IConfigurationElement config) {\r
+\r
+ // try the specific bean id the extension defines\r
+ if (data != null && data.toString().length() > 0) {\r
+ return data.toString();\r
+ }\r
+\r
+ // try the id of the config element\r
+ if (config.getAttribute("id") != null) {\r
+ return config.getAttribute("id");\r
+ }\r
+\r
+ // try the id of the extension element itself\r
+ if (config.getParent() != null\r
+ && config.getParent() instanceof IExtension) {\r
+ IExtension extensionDefinition = (IExtension) config.getParent();\r
+ return extensionDefinition.getSimpleIdentifier();\r
+ }\r
+\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.ext.rap.ui.workbench</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments />
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments />
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+ xmlns:util="http://www.springframework.org/schema/util"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi \r
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+ http://www.springframework.org/schema/beans \r
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/util\r
+ http://www.springframework.org/schema/util/spring-util-2.5.xsd">\r
+\r
+ <service interface="org.eclipse.rap.rwt.application.ApplicationConfiguration">\r
+ <service-properties>\r
+ <beans:entry key="contextName" value="ui" />\r
+ </service-properties>\r
+ <beans:bean\r
+ class="org.eclipse.rap.ui.internal.servlet.WorkbenchApplicationConfiguration" />\r
+ </service>\r
+</beans:beans>
\ No newline at end of file
--- /dev/null
+Bundle-SymbolicName: org.argeo.ext.rap.ui.workbench;singleton:=true
+Bundle-ActivationPolicy: lazy
+
+Fragment-Host: org.eclipse.rap.ui.workbench
--- /dev/null
+source.. = src/,\
+ ext/test/
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>argeo-commons-legacy</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.ext.rap.ui.workbench</artifactId>
+ <name>Extension RAP Workbench</name>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>argeo-commons</artifactId>
+ <version>2.1.84</version>
+ </parent>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
+ <artifactId>argeo-commons-legacy</artifactId>
+ <version>2.1.85-SNAPSHOT</version>
+ <name>Commons Legacy</name>
+ <packaging>pom</packaging>
+ <properties>
+ <version.argeo-tp-extras>2.1.13</version.argeo-tp-extras>
+ </properties>
+ <modules>
+ <module>org.argeo.cms.ui.workbench</module>
+ <module>org.argeo.cms.ui.workbench.rap</module>
+ <module>org.argeo.ext.rap.ui.workbench</module>
+ <module>dep</module>
+ </modules>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.tp.extras</groupId>
+ <artifactId>argeo-tp-extras</artifactId>
+ <version>${version.argeo-tp-extras}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <repositories>
+ <repository>
+ <id>argeo</id>
+ <url>http://repo.argeo.org/data/java/argeo-2.1/</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>daily</updatePolicy>
+ <checksumPolicy>warn</checksumPolicy>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>argeo-extras</id>
+ <url>http://repo.argeo.org/data/java/argeo-extras-2.1/</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>daily</updatePolicy>
+ <checksumPolicy>warn</checksumPolicy>
+ </releases>
+ </repository>
+ </repositories>
+ <profiles>
+ <profile>
+ <id>localrepo</id>
+ <repositories>
+ <repository>
+ <id>argeo-extras</id>
+ <url>http://localhost:7080/data/java/argeo-extras-2.1</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>daily</updatePolicy>
+ <checksumPolicy>warn</checksumPolicy>
+ </releases>
+ </repository>
+ </repositories>
+ </profile>
+ </profiles>
+
+</project>
\ No newline at end of file
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc</groupId>
+ <artifactId>argeo-slc</artifactId>
+ <version>2.1.17-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>legacy</artifactId>
+ <packaging>pom</packaging>
+ <name>SLC Legacy Argeo Software</name>
+ <modules>
+ <module>argeo-commons</module>
+ </modules>
+</project>
\ No newline at end of file
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.slc</groupId>
<!-- Argeo common distribution for Secured UI -->
<dependency>
- <groupId>org.argeo.commons</groupId>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
<artifactId>org.argeo.cms.ui.workbench.rap</artifactId>
- <version>${version.argeo-commons}</version>
+ <version>${version.argeo-commons-legacy}</version>
</dependency>
<!-- RAP workbench -->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.slc</groupId>
<version>${version.argeo-commons}</version>
</dependency>
<dependency>
- <groupId>org.argeo.commons</groupId>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
<artifactId>org.argeo.cms.ui.workbench</artifactId>
- <version>${version.argeo-commons}</version>
+ <version>${version.argeo-commons-legacy}</version>
</dependency>
<version>2.1.17-SNAPSHOT</version>
</dependency>
- <!-- Argeo Base dependencies -->
+ <!-- Argeo Base dependencies -->
<dependency>
<groupId>org.argeo.commons</groupId>
<artifactId>org.argeo.util</artifactId>
<type>pom</type>
<scope>provided</scope>
</dependency>
-
+
</dependencies>
</project>
\ No newline at end of file
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.slc</groupId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.argeo.commons</groupId>
+ <groupId>org.argeo.slc.legacy.commons</groupId>
<artifactId>org.argeo.cms.ui.workbench</artifactId>
- <version>${version.argeo-commons}</version>
+ <version>${version.argeo-commons-legacy}</version>
</dependency>
<!-- RAP workbench -->
+++ /dev/null
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.slc.cli;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-
-import org.argeo.osgi.boot.OsgiBoot;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.launch.Framework;
-import org.osgi.framework.launch.FrameworkFactory;
-
-/** Configures an SLC runtime and runs a process. */
-public class SlcMain implements PrivilegedAction<String> {
- public final static String NIX = "NIX";
- public final static String WINDOWS = "WINDOWS";
- public final static String SOLARIS = "SOLARIS";
-
- public final static String os;
- public final static String slcDirName = ".slc";
- final static File homeDir = new File(System.getProperty("user.home"));
-
- static {
- String osName = System.getProperty("os.name");
- if (osName.startsWith("Win"))
- os = WINDOWS;
- else if (osName.startsWith("Solaris"))
- os = SOLARIS;
- else
- os = NIX;
- }
-
- private Long timeout = 30 * 1000l;
- private final String[] args;
- private final File confDir;
- private final File dataDir;
- private final File modulesDir;
-
- private final List<String> bundlesToStart = new ArrayList<String>();
-
- public SlcMain(String[] args, File confDir, File dataDir, File modulesDir) {
- this.args = args;
- this.confDir = confDir;
- this.dataDir = dataDir;
- this.modulesDir = modulesDir;
-
- bundlesToStart.add("org.eclipse.equinox.cm");
- bundlesToStart.add("org.argeo.cms");
- bundlesToStart.add("org.eclipse.gemini.blueprint.extender");
- bundlesToStart.add("org.argeo.slc.agent");
- bundlesToStart.add("org.argeo.slc.agent.jcr");
-
- // bundlesToStart.add("org.springframework.osgi.extender");
- // bundlesToStart.add("org.argeo.node.repo.jackrabbit");
- // bundlesToStart.add("org.argeo.security.dao.os");
- // bundlesToStart.add("org.argeo.slc.node.jackrabbit");
- // bundlesToStart.add("org.argeo.slc.agent");
- // bundlesToStart.add("org.argeo.slc.agent.jcr");
- // if (args.length == 0)
- // bundlesToStart.add("org.argeo.slc.support.equinox");
- // bundlesToStart.add("org.argeo.slc.agent.cli");
- }
-
- public String run() {
- long begin = System.currentTimeMillis();
-
- Framework framework = null;
- try {
- info("## Date : " + new Date());
- info("## Data : " + dataDir.getCanonicalPath());
-
- // Start Equinox
- ServiceLoader<FrameworkFactory> ff = ServiceLoader.load(FrameworkFactory.class);
- FrameworkFactory frameworkFactory = ff.iterator().next();
- Map<String, String> configuration = new HashMap<String, String>();
- configuration.put("osgi.configuration.area", confDir.getCanonicalPath());
- configuration.put("osgi.instance.area", dataDir.getCanonicalPath());
- // Do clean
- configuration.put("osgi.clean", "true");
- if (args.length == 0) {
- configuration.put("osgi.console", "");
- }
-
- // Spring configs currently require System properties
- System.getProperties().putAll(configuration);
-
- framework = frameworkFactory.newFramework(configuration);
- framework.start();
- BundleContext bundleContext = framework.getBundleContext();
-
- // OSGi bootstrap
- OsgiBoot osgiBoot = new OsgiBoot(bundleContext);
-
- // working copy modules
- if (modulesDir.exists())
- osgiBoot.installUrls(osgiBoot.getBundlesUrls(modulesDir.getCanonicalPath() + ";in=*;ex=.gitignore"));
-
- // system modules
- if (System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BUNDLES) != null)
- osgiBoot.installUrls(osgiBoot.getBundlesUrls(System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BUNDLES)));
- else
- osgiBoot.installUrls(osgiBoot.getBundlesUrls(System.getProperty("user.home") + "/.slc/modules/;in=**"));
-
- // Start runtime
- osgiBoot.startBundles(bundlesToStart);
-
- // Find SLC Agent
- ServiceReference sr = null;
- while (sr == null) {
- sr = bundleContext.getServiceReference("org.argeo.slc.execution.SlcAgentCli");
- if (System.currentTimeMillis() - begin > timeout)
- throw new RuntimeException("Cannot find SLC agent CLI");
- Thread.sleep(100);
- }
- Object agentCli = bundleContext.getService(sr);
-
- // Initialization completed
- long duration = System.currentTimeMillis() - begin;
- info("[[ Initialized in " + (duration / 1000) + "s " + (duration % 1000) + "ms ]]");
-
- if (args.length == 0)
- return null;// console mode
-
- // Subject.doAs(Subject.getSubject(AccessController.getContext()),
- // new AgentCliCall(agentCli));
- Class<?>[] parameterTypes = { String[].class };
- Method method = agentCli.getClass().getMethod("process", parameterTypes);
- Object[] methodArgs = { args };
- Object ret = method.invoke(agentCli, methodArgs);
-
- // Shutdown OSGi runtime
- framework.stop();
- framework.waitForStop(60 * 1000);
-
- return ret.toString();
- } catch (Exception e) {
- // Shutdown OSGi runtime
- if (framework != null)
- try {
- framework.stop();
- framework.waitForStop(15 * 1000);
- } catch (Exception silent) {
- }
- throw new RuntimeException("Cannot run SLC command line", e);
- } finally {
-
- }
- }
-
- public static void main(String[] args) {
- try {
- // Prepare directories
- File executionDir = new File(System.getProperty("user.dir"));
- File slcDir;
- Boolean isTransient = false;
- if (isTransient) {
- File tempDir = new File(System.getProperty("java.io.tmpdir") + "/" + System.getProperty("user.name"));
- slcDir = new File(tempDir, "slc-" + UUID.randomUUID().toString());
- slcDir.mkdirs();
- System.setProperty("argeo.node.repo.configuration", "osgibundle:repository-memory.xml");
- } else {
- slcDir = findSlcDir(executionDir);
- if (slcDir == null) {
- slcDir = new File(executionDir, slcDirName);
- slcDir.mkdirs();
- info("## Creating an SLC node at " + slcDir + " ...");
- }
- }
-
- File dataDir = new File(slcDir, "data");
- if (!dataDir.exists())
- dataDir.mkdirs();
-
- File confDir = new File(slcDir, "conf");
- if (!confDir.exists())
- confDir.mkdirs();
-
- File modulesDir = new File(slcDir, "modules");
-
- // JAAS
- // File jaasFile = new File(confDir, "jaas.config");
- // if (!jaasFile.exists())
- // copyResource("/org/argeo/slc/cli/jaas.config", jaasFile);
- // System.setProperty("java.security.auth.login.config",
- // jaasFile.getCanonicalPath());
-
- // log4j
- File log4jFile = new File(confDir, "log4j.properties");
- if (!log4jFile.exists())
- copyResource("/org/argeo/slc/cli/log4j.properties", log4jFile);
- System.setProperty("log4j.configuration", "file://" + log4jFile.getCanonicalPath());
- // Run as a privileged action
- // LoginContext lc = new LoginContext(os);
- // lc.login();
- //
- // Subject subject =
- // Subject.getSubject(AccessController.getContext());
- // Subject.doAs(subject, new SlcMain(args, confDir, dataDir,
- // modulesDir));
- SlcMain slcMain = new SlcMain(args, confDir, dataDir, modulesDir);
- slcMain.run();
- if (args.length != 0)
- System.exit(0);
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
- }
-
- /**
- * Recursively look in parent directories for a directory named
- * {@link #slcDirName}
- */
- protected static File findSlcDir(File currentDir) {
- File slcDir = new File(currentDir, slcDirName);
- // covers the use case of running from the home directory
- if (slcDir.exists() && slcDir.isDirectory())
- return slcDir;
- File parentDir = currentDir.getParentFile();
- if (parentDir == null)
- return null;
- try {
- // ~/.slc reserved for agent
- if (parentDir.getCanonicalPath().equals(homeDir.getCanonicalPath()))
- return null;
- } catch (IOException e) {
- throw new RuntimeException("Cannot check home directory", e);
- }
- return findSlcDir(parentDir);
- }
-
- protected static void copyResource(String resource, File targetFile) {
- InputStream input = null;
- FileOutputStream output = null;
- try {
- input = SlcMain.class.getResourceAsStream(resource);
- output = new FileOutputStream(targetFile);
- byte[] buf = new byte[8192];
- while (true) {
- int length = input.read(buf);
- if (length < 0)
- break;
- output.write(buf, 0, length);
- }
- } catch (Exception e) {
- throw new RuntimeException("Cannot write " + resource + " file to " + targetFile, e);
- } finally {
- try {
- input.close();
- } catch (Exception ignore) {
- }
- try {
- output.close();
- } catch (Exception ignore) {
- }
- }
-
- }
-
- protected static void info(Object msg) {
- System.out.println(msg);
- }
-
- protected static void err(Object msg) {
- System.err.println(msg);
- }
-
- protected static void debug(Object msg) {
- System.out.println(msg);
- }
-
-}
-
-// private String bundlesToInstall = System.getProperty("user.home")
-// +
-// "/dev/src/slc/dep/org.argeo.slc.dep.minimal/target/dependency;in=*.jar,"
-// + System.getProperty("user.home")
-// + "/dev/src/slc/demo/modules;in=*;ex=pom.xml;ex=.svn";
-
-// ServiceTracker agentTracker = new ServiceTracker(bundleContext,
-// "org.argeo.slc.execution.SlcAgentCli", null);
-// agentTracker.open();
-// final Object agentCli = agentTracker.waitForService(30 * 1000);
-// if (agentCli == null)
-// throw new RuntimeException("Cannot find SLC agent CLI");
-
-// protected class AgentCliCall implements PrivilegedAction<String> {
-// private final Object agentCli;
-//
-// public AgentCliCall(Object agentCli) {
-// super();
-// this.agentCli = agentCli;
-// }
-//
-// public String run() {
-// try {
-// Class<?>[] parameterTypes = { String[].class };
-// Method method = agentCli.getClass().getMethod("process",
-// parameterTypes);
-// Object[] methodArgs = { args };
-// Object ret = method.invoke(agentCli, methodArgs);
-// return ret.toString();
-// } catch (Exception e) {
-// throw new RuntimeException("Cannot run "
-// + Arrays.toString(args) + " on " + agentCli, e);
-// }
-// }
-//
-// }
<parent>
<groupId>org.argeo.commons</groupId>
<artifactId>argeo-commons</artifactId>
- <version>2.1.82</version>
+ <version>2.1.85-SNAPSHOT</version>
</parent>
<groupId>org.argeo.slc</groupId>
<artifactId>argeo-slc</artifactId>
<developmentCycle.slc>2.1</developmentCycle.slc>
<version.argeo-tp-extras>2.1.13</version.argeo-tp-extras>
+
+ <version.argeo-commons-legacy>2.1.85-SNAPSHOT</version.argeo-commons-legacy>
</properties>
<modules>
<!-- Runtime -->
<!-- E4 -->
<module>org.argeo.slc.e4</module>
- <!-- UI -->
+ <!-- Legacy UI -->
+ <module>legacy</module>
<module>org.argeo.slc.client.ui</module>
<module>org.argeo.slc.client.ui.dist</module>
<module>org.argeo.slc.client.rap</module>