exo-jcr SVN: r2445 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl: config and 1 other directory.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-05-28 10:47:38 -0400 (Fri, 28 May 2010)
New Revision: 2445
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
Log:
EXOJCR-735 : Code formatting.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 14:17:22 UTC (rev 2444)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 14:47:38 UTC (rev 2445)
@@ -535,7 +535,7 @@
private void registerWorkspacesComponents() throws RepositoryException, RepositoryConfigurationException
{
- // System workspace should be first initialize.
+ // System workspace should be first initialized.
for (WorkspaceEntry we : config.getWorkspaceEntries())
{
if (we.getName().equals(config.getSystemWorkspaceName()))
@@ -543,7 +543,7 @@
registerWorkspace(we);
}
}
-
+
// Initialize other (non system) workspaces.
for (WorkspaceEntry we : config.getWorkspaceEntries())
{
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 14:17:22 UTC (rev 2444)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 14:47:38 UTC (rev 2445)
@@ -254,14 +254,14 @@
if ((configurationPersister != null && configurationPersister.hasConfig()))
{
initFromStream(configurationService.getInputStream(param.getValue()));
-
+
// Will be merged extension repository configuration with configuration from persister.
- if (!configExtensionPaths.isEmpty())
+ if (!configExtensionPaths.isEmpty())
{
- String[] paths = (String[])configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
+ String[] paths = (String[]) configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
for (int i = paths.length - 1; i >= 0; i--)
{
- merge(configurationService.getInputStream(paths[i]));
+ merge(configurationService.getInputStream(paths[i]));
}
// Store the merged configuration
if (configurationPersister != null)
@@ -273,7 +273,7 @@
else
{
- String[] paths = (String[])configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
+ String[] paths = (String[]) configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
for (int i = paths.length - 1; i >= 0; i--)
{
// We start from the last one because as it is the one with highest priorityn
13 years, 11 months
exo-jcr SVN: r2444 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl: config and 1 other directory.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-05-28 10:17:22 -0400 (Fri, 28 May 2010)
New Revision: 2444
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
Log:
EXOJCR-735 : Refactoring method RepositoryContainer.registerWorkspacesComponents(). Remove unused WorkspaceOrderComparator.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 10:29:30 UTC (rev 2443)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 14:17:22 UTC (rev 2444)
@@ -535,30 +535,22 @@
private void registerWorkspacesComponents() throws RepositoryException, RepositoryConfigurationException
{
- List<WorkspaceEntry> wsEntries = new ArrayList<WorkspaceEntry>();
-
- for (WorkspaceEntry ws : config.getWorkspaceEntries())
+ // System workspace should be first initialize.
+ for (WorkspaceEntry we : config.getWorkspaceEntries())
{
- if (ws.getName().equals(config.getSystemWorkspaceName()))
+ if (we.getName().equals(config.getSystemWorkspaceName()))
{
- if (wsEntries.size() == 0)
- {
- wsEntries.add(ws);
- }
- else
- {
- wsEntries.add(0, ws);
- }
- }
- else
- {
- wsEntries.add(ws);
+ registerWorkspace(we);
}
}
- for (int i = 0; i < wsEntries.size(); i++)
+ // Initialize other (non system) workspaces.
+ for (WorkspaceEntry we : config.getWorkspaceEntries())
{
- registerWorkspace(wsEntries.get(i));
+ if (!we.getName().equals(config.getSystemWorkspaceName()))
+ {
+ registerWorkspace(we);
+ }
}
}
@@ -591,24 +583,5 @@
ntManager.start();
}
-
- /**
- * Workspaces order comparator.
- *
- */
- private static class WorkspaceOrderComparator implements Comparator<WorkspaceEntry>
- {
- private final String sysWs;
-
- private WorkspaceOrderComparator(String sysWs)
- {
- this.sysWs = sysWs;
- }
-
- public int compare(WorkspaceEntry o1, WorkspaceEntry o2)
- {
- String n1 = o1.getName();
- return n1.equals(sysWs) ? -1 : 0;
- }
- }
+
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 10:29:30 UTC (rev 2443)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 14:17:22 UTC (rev 2444)
@@ -251,10 +251,11 @@
{
try
{
- if (configExtensionPaths.isEmpty() || (configurationPersister != null && configurationPersister.hasConfig()))
+ if ((configurationPersister != null && configurationPersister.hasConfig()))
{
initFromStream(configurationService.getInputStream(param.getValue()));
+ // Will be merged extension repository configuration with configuration from persister.
if (!configExtensionPaths.isEmpty())
{
String[] paths = (String[])configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
13 years, 11 months
exo-jcr SVN: r2443 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl: config and 1 other directory.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-05-28 06:29:30 -0400 (Fri, 28 May 2010)
New Revision: 2443
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
Log:
EXOJCR-735 : Add merge extend configuration with persisted config.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 09:59:52 UTC (rev 2442)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2010-05-28 10:29:30 UTC (rev 2443)
@@ -62,6 +62,7 @@
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -534,8 +535,27 @@
private void registerWorkspacesComponents() throws RepositoryException, RepositoryConfigurationException
{
- List<WorkspaceEntry> wsEntries = config.getWorkspaceEntries();
- Collections.sort(wsEntries, new WorkspaceOrderComparator(config.getSystemWorkspaceName()));
+ List<WorkspaceEntry> wsEntries = new ArrayList<WorkspaceEntry>();
+
+ for (WorkspaceEntry ws : config.getWorkspaceEntries())
+ {
+ if (ws.getName().equals(config.getSystemWorkspaceName()))
+ {
+ if (wsEntries.size() == 0)
+ {
+ wsEntries.add(ws);
+ }
+ else
+ {
+ wsEntries.add(0, ws);
+ }
+ }
+ else
+ {
+ wsEntries.add(ws);
+ }
+ }
+
for (int i = 0; i < wsEntries.size(); i++)
{
registerWorkspace(wsEntries.get(i));
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 09:59:52 UTC (rev 2442)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-28 10:29:30 UTC (rev 2443)
@@ -254,6 +254,20 @@
if (configExtensionPaths.isEmpty() || (configurationPersister != null && configurationPersister.hasConfig()))
{
initFromStream(configurationService.getInputStream(param.getValue()));
+
+ if (!configExtensionPaths.isEmpty())
+ {
+ String[] paths = (String[])configExtensionPaths.toArray(new String[configExtensionPaths.size()]);
+ for (int i = paths.length - 1; i >= 0; i--)
+ {
+ merge(configurationService.getInputStream(paths[i]));
+ }
+ // Store the merged configuration
+ if (configurationPersister != null)
+ {
+ retain();
+ }
+ }
}
else
{
13 years, 11 months
exo-jcr SVN: r2442 - in jcr/trunk/docs/reference/en/src/main: docbook/en-US/modules/ws and 1 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-05-28 05:59:52 -0400 (Fri, 28 May 2010)
New Revision: 2442
Added:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml
jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
Modified:
jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
Log:
EXOJCR-731: move ws doc to docboof format
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/central-authentication-service-configuration.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Central Authentication Service Configuration</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>Central Authentication Service (CAS) is a Web Single Sign-On
+ (WebSSO), developped by JA-SIG as an open-source project. CAS, like any
+ WebSSO, is very interesting in information systems where many applications
+ share a common users repository. When you enable CAS on all the
+ application, a user would log once and only once and will be recognized
+ and authentified into all the applications.</para>
+
+ <para>CAS documentation explains how to configure in details any
+ environment, that is mainly a configuration of a Web application to
+ authenticate itself against the CAS Server instead of an internal
+ mechanism. This documentation explain how to configure eXo Platform to
+ delegate the authentication to the CAS server and let it ensure the
+ single-sign-one between all the applications of an IS.</para>
+ </section>
+
+ <section>
+ <title>CAS configuration</title>
+
+ <para>This article try to explain how to configure CAS server and client
+ for exo. For this example we will use 2 the same tomcat instance, but one
+ for it has additation CAS server.</para>
+
+ <para>This configuration is not very useful, but very good example for
+ configuration CAS.</para>
+
+ <para>Tomcat 1 deployed on windows 2003 - this is CAS server, tomcat 2 on
+ Ubuntu 7.10.</para>
+
+ <section>
+ <title>Configure CAS server</title>
+
+ <para><command>(DNS name: test01-srv.exoua-int)</command></para>
+
+ <para>1.Certificates.</para>
+
+ <programlisting>E:/Program Files>cd java
+E:/Program Files/Java>cd jre1.5.0_11
+E:/Program Files/Java/jre1.5.0_11>cd bin
+E:/Program Files/Java/jre1.5.0_11/bin>keytool -genkey -alias tomcat -keypass 123456 -keyalg RSA
+Enter keystore password: 123456
+What is your first and last name?
+ [Unknown]: test01-srv.exoua-int
+What is the name of your organizational unit?
+ [Unknown]: .
+What is the name of your organization?
+ [Unknown]: .
+What is the name of your City or Locality?
+ [Unknown]: .
+What is the name of your State or Province?
+ [Unknown]: .
+What is the two-letter country code for this unit?
+ [Unknown]: UA
+Is CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA correct?
+ [no]: yes
+
+E:/Program Files/Java/jre1.5.0_11/bin>keytool -export -alias tomcat -keypass 123456 -file server.crt
+Enter keystore password: 123456
+Certificate stored in file <server.crt></programlisting>
+
+ <para>This is optional, I just want to have the same password for
+ storage %JRE_HOME%/lib/security/cacerts.</para>
+
+ <programlisting>E:/Program Files/Java/jre1.5.0_11/bin>keytool -storepasswd -keystore ../lib/security/cacerts
+Enter keystore password: changeit
+New keystore password: 123456
+Re-enter new keystore password: 123456</programlisting>
+
+ <para>Continue with certificates.</para>
+
+ <programlisting>E:/Program Files/Java/jre1.5.0_11/bin>keytool -import -file server.crt -keypass 123456 -keystore ../lib/security/cacerts
+Enter keystore password: 123456
+Owner: CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA
+Issuer: CN=test01-srv.exoua-int, OU=., O=., L=., ST=., C=UA
+Serial number: 4810c6c5
+Valid from: Fri Apr 24 20:33:36 HST 2008 until: Thu Jul 23 20:33:36 HST 2008
+Certificate fingerprints:
+MD5: CC:3B:FB:FB:AE:12:AD:FB:3E:D 5:98:CB:2E:3B:0A:AD
+SHA1: A1:16:80:68:39:C7:58:EA:2F:48:59:AA:1D:73:5F:56:78:CE:A4:CE
+Trust this certificate? [no]: yes
+Certificate was added to keystore
+
+E:/Program Files/Java/jre1.5.0_11/bin></programlisting>
+
+ <para>2. Now edit server.xml file for tomcat (we are using 6.0.13
+ everywhere).Uncomment configuration for SSL connection end edit it, it
+ must looks as this:</para>
+
+ <programlisting><Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+maxThreads="150" scheme="https" secure="true"
+clientAuth="false" sslProtocol="TLS"
+keystoreFile="E:/Documents and Settings/admin/.keystore"
+keystorePass="123456"
+keyAlias="tomcat"
+truststoreFile="E:/Program Files/Java/jre1.5.0_11/lib/security/cacerts"
+truststorePass="123456" /></programlisting>
+
+ <para>3. Now configure client part of CAS, as example we will use
+ portal/private/* .Edit file /portal/WEB-INF/web.xml.</para>
+
+ <programlisting><context-param>
+ <param-name>serverName</param-name>
+ <param-value>http://test01-srv.exoua-int:8080</param-value>
+</context-param></programlisting>
+
+ <para>Configure client, in this example we will protect
+ /portal/private/* resource. Note: These filter must be add before this
+ filter "SetCurrentIdentityFilter", the same think for
+ filter-mapping.</para>
+
+ <programlisting><filter>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
+</filter>
+<filter>
+ <filter-name>AuthenticationFilter</filter-name>
+ <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
+ <init-param>
+ <param-name>casServerLoginUrl</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas/login</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
+ <init-param>
+ <param-name>casServerUrlPrefix</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectAfterValidation</param-name>
+ <param-value>true</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
+</filter>
+<!-- eXo -->
+<filter>
+ <filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <filter-class>org.exoplatform.services.security.cas.client.impl.BaseIdentityInitializerFilterImpl</filter-class>
+</filter>
+<!-- end exo -->
+....
+<filter-mapping>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>AuthenticationFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<!-- exo -->
+<filter-mapping>
+ <filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <url-pattern>/private/*</url-pattern>
+</filter-mapping>
+<!-- end exo -->
+....
+<listener>
+ <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
+</listener>
+....
+<!-- exo -->
+<servlet>
+ <servlet-name>LogoutServlet</servlet-name>
+ <servlet-class>org.exoplatform.services.security.cas.client.impl.LogoutServlet</servlet-class>
+ <init-param>
+ <param-name>casServerLogoutUrl</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas/logout</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectToUrl</param-name>
+ <param-value>http://test01-srv.exoua-int:8080/portal/public/classic</param-value>
+ </init-param>
+</servlet>
+<!-- end exo -->
+.....
+<!-- exo -->
+<servlet-mapping>
+ <servlet-name>LogoutServlet</servlet-name>
+ <url-pattern>/logout/*</url-pattern>
+</servlet-mapping>
+<!-- end exo -->
+....</programlisting>
+
+ <para>4. Download and build code from <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/trunk/security...</link></para>
+
+ <para>5. Download and put cas-client-core-3.1.1.jar in
+ CATALINA_HOME%/lib directory.</para>
+
+ <para>6. Download CAS server source code and build it or download
+ binary. Put cas.war in webapps directoryChange configuration in file
+ /cas/WEB-INF/deployConfigContext.xml. Comment test authenticator and add
+ new one.</para>
+
+ <programlisting><!--
+<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
+-->
+<!-- will check username and password at remote host -->
+<bean class="org.exoplatform.services.security.cas.server.HTTPAuthenticationHandler"
+p:authenticationURL="https://ubu.exoua-int:8443/portal/login" /></programlisting>
+
+ <para>7. Download and build code which can do remote
+ authentication.Download and build code from <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/trunk/security...</link>,
+ andput it cas/WEB-INF/lib directory. This CAS server side handler which
+ can call remote eXo authenticatiob service via HTTP.In this case
+ validation of username/password wiil be done at ubu.exoua-int, but
+ authentication sever (CAS) will be at test01-srv.exoua-int</para>
+ </section>
+
+ <section>
+ <title>Configure other tomcat instance</title>
+
+ <para><command>Configure other tomcat instance, deploy it on Ubuntu 7.10
+ (DNS name: ubu.exoua-int).</command></para>
+
+ <para>1. Generate certificates for CAS client. The same as for previous
+ but change name to ubu.exoua-int.</para>
+
+ <para>2. Edit server.xml file for tomcat.</para>
+
+ <programlisting><Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+maxThreads="150" scheme="https" secure="true"
+clientAuth="false" sslProtocol="TLS"
+keystoreFile="/home/andrew/.keystore"
+keystorePass="123456"
+keyAlias="tomcat"
+truststoreFile="/home/andrew/lib/java/jre/lib/security/cacerts"
+truststorePass="123456" /></programlisting>
+
+ <para>3. Edit file portal/WEB-INF/web.xml, add next strings in it.
+ Change context parameter.</para>
+
+ <programlisting><context-param>
+ <param-name>serverName</param-name>
+ <param-value>http://ubu.exoua-int:8080</param-value>
+</context-param></programlisting>
+
+ <para>Filters configuration must be the same as in client part on
+ tomcat1. But add one more servlet which will check
+ username/password.</para>
+
+ <programlisting><filter>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
+</filter>
+<filter>
+ <filter-name>AuthenticationFilter</filter-name>
+ <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
+ <init-param>
+ <param-name>casServerLoginUrl</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas/login</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
+ <init-param>
+ <param-name>casServerUrlPrefix</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectAfterValidation</param-name>
+ <param-value>true</param-value>
+ </init-param>
+</filter>
+<filter>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
+</filter>
+<!-- exo -->
+<filter>
+ <filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <filter-class>org.exoplatform.services.security.cas.client.impl.BaseIdentityInitializerFilterImpl\
+</filter-class>
+</filter>
+<!-- end exo -->
+....
+<filter-mapping>
+ <filter-name>SingleSignOutFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>AuthenticationFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>Cas20ProxyReceivingTicketValidationFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<filter-mapping>
+ <filter-name>HttpServletRequestWrapperFilter</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<!-- exo -->
+<filter-mapping>
+ <filter-name>BaseIdentityInitializerFilterImpl</filter-name>
+ <url-pattern>/private/&#42;</url-pattern>
+</filter-mapping>
+<!-- end exo -->
+....
+<listener>
+ <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
+</listener>
+....
+<!-- exo -->
+<servlet>
+ <servlet-name>BaseHTTPUsernamePasswordValidator</servlet-name>
+ <servlet-class>org.exoplatform.services.security.cas.client.impl.BaseHTTPUsernamePasswordValidatorImpl</servlet-class>
+</servlet>
+<servlet>
+ <servlet-name>LogoutServlet</servlet-name>
+ <servlet-class>org.exoplatform.services.security.cas.client.impl.LogoutServlet</servlet-class>
+ <init-param>
+ <param-name>casServerLogoutUrl</param-name>
+ <param-value>https://test01-srv.exoua-int:8443/cas/logout</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectToUrl</param-name>
+ <param-value>http://ubu.exoua-int:8080/portal/public/classic</param-value>
+ </init-param>
+</servlet>
+<!-- end exo -->
+.....
+<!-- exo -->
+<servlet-mapping>
+ <servlet-name>BaseHTTPUsernamePasswordValidator</servlet-name>
+ <url-pattern>/login/&#42;</url-pattern>
+</servlet-mapping>
+<servlet-mapping>
+ <servlet-name>LogoutServlet</servlet-name>
+ <url-pattern>/logout/&#42;</url-pattern>
+</servlet-mapping>
+<!-- end exo -->
+<!-- not use default authentification-->
+<!--
+<security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user authentication</web-resource-name>
+ <url-pattern>/private/&#42;</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>users</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>FORM</auth-method>
+ <realm-name>exo-domain</realm-name>
+ <form-login-config>
+ <form-login-page>/login/jsp/login.jsp</form-login-page>
+ <form-error-page>/login/jsp/login.jsp</form-error-page>
+ </form-login-config>
+ </login-config>
+
+ <security-role>
+ <description>a simple user role</description>
+ <role-name>users</role-name>
+ </security-role>
+
+ <security-role>
+ <description>the admin role</description>
+ <role-name>admin</role-name>
+ </security-role>
+-->
+<!-- end web.xml file-->
+....</programlisting>
+
+ <para>4. Download and build code from <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/trunk/security...</link></para>
+
+ <para>5. Download and put cas-client-core-3.1.1.jar in
+ CATALINA_HOME%/lib directory.</para>
+
+ <para>6. Now get trusted certificate for CAS server instance. To do this
+ download and compile this file: <link
+ linkend="???">http://blogs.sun.com/andreas/resource/InstallCert.java</link>
+ Then run it:</para>
+
+ <programlisting>java InstallCert test01-srv.exoua-int:8443 123456</programlisting>
+
+ <para>Change 123456 to actual password for keystore. You can see some
+ exception but finally you must see info about certificates and prompt
+ about adding it in storage. Select certificate, usually type 1 end press
+ Enter.</para>
+
+ <para>Finish!!!</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Run both servers, and try open one of protected URLs, for example
+ <link
+ linkend="???">http://test01-srv.exoua-int:8080/portal/private/classic</link>.
+ Accept certificates, and in login page username/password: root/exo. You
+ must get private area in portal as root, then open other protected
+ resource on server 'ubu.exoua-int', <link
+ linkend="???">http://ubu.exoua-int:8080/portal/private/classic</link>.
+ And you must get this private area in other portal <command>without
+ login</command>. If you get it then SSO for login work as well.</para>
+
+ <para>No try logout on 'ubu.exoua-int'. To do it directly from portal
+ one groovy script must be modified, but it is not described here.</para>
+
+ <para>After logout from 'ubu.exoua-int' you should be asked about login
+ at 'test01-srv.exoua-int'. The SSO for logout work well also.</para>
+
+ <para>That is all!</para>
+
+ <para>If it works as described above, then configuration right and SSO
+ works.</para>
+ </section>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster-bench.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd Cluster Bench</title>
+
+ <section>
+ <title>How we test</title>
+
+ <para>We simple open many connection, all client subscribing to one
+ channel, we don't send any message to client, they reconnect through
+ 120000 ms. Settings for cometd servlet.</para>
+
+ <programlisting><servlet>
+ <servlet-name>cometd</servlet-name>
+ <servlet-class>org.mortbay.cometd.continuation.EXoContinuationCometdServlet</servlet-class>
+ <init-param>
+ <param-name>filters</param-name>
+ <param-value>/WEB-INF/filters.json</param-value>
+ </init-param>
+ <init-param>
+ <param-name>timeout</param-name>
+ <param-value>120000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>interval</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>multiFrameInterval</param-name>
+ <param-value>1500</param-value>
+ </init-param>
+ <init-param>
+ <param-name>logLevel</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>JSONCommented</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>alwaysResumePoll</param-name>
+ <param-value>false</param-value> <!-- use true for x-site cometd -->
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet></programlisting>
+ </section>
+
+ <section>
+ <title>Environment</title>
+
+ <para>Test running on our server for testing (Tornado)</para>
+
+ <para>Processor : Intel(R) Xeon(R) CPU E5345 @ 2.33GHz (8 cores)</para>
+
+ <para>RAM : 16 GB</para>
+
+ <para>java version "1.5.0_15" (64-bit)</para>
+ </section>
+
+ <section>
+ <title>Result</title>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry align="center">Connection</entry>
+
+ <entry align="center">Heap (JProfiler), mb</entry>
+
+ <entry align="center">Virt (top),gb</entry>
+
+ <entry align="center">res (top), gb</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1000</entry>
+
+ <entry>239</entry>
+
+ <entry>-</entry>
+
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry>2000</entry>
+
+ <entry>318</entry>
+
+ <entry>-</entry>
+
+ <entry>-</entry>
+ </row>
+
+ <row>
+ <entry>3000</entry>
+
+ <entry>450</entry>
+
+ <entry>6</entry>
+
+ <entry>1.36</entry>
+ </row>
+
+ <row>
+ <entry>4000</entry>
+
+ <entry>610</entry>
+
+ <entry>7.2</entry>
+
+ <entry>1.6</entry>
+ </row>
+
+ <row>
+ <entry>5000</entry>
+
+ <entry>767</entry>
+
+ <entry>12.9</entry>
+
+ <entry>1.7</entry>
+ </row>
+
+ <row>
+ <entry>6000</entry>
+
+ <entry>895</entry>
+
+ <entry>14.4</entry>
+
+ <entry>1.8</entry>
+ </row>
+
+ <row>
+ <entry>7000</entry>
+
+ <entry>1004</entry>
+
+ <entry>15.5</entry>
+
+ <entry>2.2</entry>
+ </row>
+
+ <row>
+ <entry>8000</entry>
+
+ <entry>1116</entry>
+
+ <entry>17.3</entry>
+
+ <entry>2.6</entry>
+ </row>
+
+ <row>
+ <entry>9000</entry>
+
+ <entry>1295</entry>
+
+ <entry>29.6</entry>
+
+ <entry>9.8</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/cometd-bench.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>In screenshot red line show thousand of connection. Then count of
+ connection be 9000 the test fail, with exception connection
+ timeout.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd-cluster.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd cluster</title>
+
+ <section>
+ <title>Motivation</title>
+
+ <para>When we run Stress Testing Cometd (Jetty implementation) <link
+ linkend="???">http://docs.codehaus.org/display/JETTY/Stress+Testing+Cometd</link>
+ we see that if we connect many clients, deliver message latency tends to
+ grow up. This situation described in article "20,000 Reasons Why Comet
+ Scales". <link
+ linkend="???">http://cometdaily.com/2008/01/07/20000-reasons-that-comet-scales/</link>
+ So, in order to support a lot of concurrent cometd connections we need a
+ mean to horizontally scale eXo cometd support.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/cometd-cluster.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>1- Getting base URL for cometd connection (one of the node in cometd
+ cluster)</para>
+
+ <para>2 - Getting userToken at cometd server (it need for subscribing on
+ channel)</para>
+
+ <para>3 - Sending message from Exo-server</para>
+
+ <para>LoadBalancer - component that give base URL of one of free cometd
+ server.</para>
+
+ <para>ContinuationServiceDelegate - component that send message from
+ Exo-server to client via cometd server there client is registered</para>
+
+ <para>RESTContinuationService - component that receive message from
+ ContinuationServiceDelegate and delegate it to ContinuationServer and send
+ userToken generated by ContinuationServer for user.</para>
+
+ <para>ContinuationService - component that provide cometd
+ connection.</para>
+ </section>
+
+ <section>
+ <title>How it works</title>
+
+ <para>To start work with cometd service the client should send request to
+ Exo-server with the username, receive with response URL one of cometd
+ servers (1 - on the scheme). This URL gives out LoadBalancer using the
+ information set in a configuration</para>
+
+ <programlisting><init-params>
+ <object-param>
+ <name>cometd.lb.configuration</name>
+ <description>cometd lb nodes</description>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl$LoadBalancerConf">
+ <field name="nodes">
+ <collection type="java.util.ArrayList">
+ <value>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>1</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8080</string>
+ </field>
+ <field name="maxConnection">
+ <int>10</int>
+ </field>
+ </object>
+ </value>
+ <value>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>2</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8081</string>
+ </field>
+ <field name="maxConnection">
+ <int>15</int>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+</init-params></programlisting>
+
+ <para>In the above configuration we described two cometd-cluseter nodes
+ of. Let's consider one of them.</para>
+
+ <para>1 - are unique the identifier of node (id) http://localhost:8080 -
+ base URL 15 - the maximum number of the connected clients. LoadBalancer
+ chooses one of node in cometd cluster (on which connection is possible)
+ and associate with a name of the user! Now the client know on that cometd
+ server connection is possible, for this purpose it is necessary to request
+ userToken on cometd server(2). As for this need do request on other domain
+ client must use framework that allowed cross-domain-ajax. We have
+ framework that can do this task, how use this framework describe in
+ article - Framework for cross-domain AJAX. After client receive userToken
+ the client can do cometd-registration.</para>
+
+ <para>Example: the Client with a name exo1 wishes to be connected to
+ cometd to service. It is necessary to make HTTP request (GET) on
+ Exo-server URL = "http://localhost:8080/rest/cometdurl/exo1" with the
+ answer receives a base URL of cometd server, it can be as a remote server
+ or local. We will assume that we use cluster and receive some thing like
+ this "http://192.168.0.21:8080". Further it is necessary get userToken
+ already from cometd server for this purpose do request (GET) URL
+ ="http://192.168.0.22:8081/rest/gettoken/exo1", after that we do standard
+ procedure for cometd connections.</para>
+
+ <para>Then it is necessary to send the message to client
+ ContinuationServiceDelegate requests at LoadBalancer the cometd server
+ address on which the client is registered sends the message in format JSON
+ on cometd server should be RESTContinuationService which to accept the
+ message and to transfer them to ContinuationService (3)</para>
+
+ <para>Example: we will want to send the message to the client exo1. For
+ this purpose ContinuationServiceDelegate requests to LoadBalancer the
+ information on that to what server the given user is connected, we will
+ receive necessary URL http://192.168.0.22:8081) and do HTTP request (POST)
+ on comets a server, URL =
+ "http://192.168.0.22:8080/rest/sendprivatemessage/" in a body the message
+ in format JSON is transferred, RESTContinuationService having received the
+ given message transfers it ContinuationService which already in turn
+ delivers it to the client.</para>
+
+ <programlisting><configuration>
+ <component>
+ <type>org.exoplatform.ws.frameworks.cometd.ContinuationService</type>
+ </component>
+ <component>
+ <key>org.mortbay.cometd.continuation.AbstractBayeux</key>
+ <type>org.mortbay.cometd.continuation.EXoContinuationBayeux</type>
+ </component>
+ <component>
+ <key>org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceDelegate</key>
+ <type>org.exoplatform.ws.frameworks.cometd.transport.ContinuationServiceRemoteDelegate</type>
+ </component>
+ <component>
+ <type>org.exoplatform.ws.frameworks.cometd.transport.RESTContinuationService</type>
+ </component>
+ <component>
+ <type>org.exoplatform.ws.frameworks.cometd.loadbalancer.RESTLoadBalancerService</type>
+ </component>
+ <component>
+ <key>org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancer</key>
+ <type>org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl</type>
+ <init-params>
+ <object-param>
+ <name>cometd.lb.configuration</name>
+ <description>cometd lb nodes</description>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.LoadBalancerImpl$LoadBalancerConf">
+ <field name="nodes">
+ <collection type="java.util.ArrayList">
+ <value>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>1</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8080</string>
+ </field>
+ <field name="maxConnection">
+ <int>10</int>
+ </field>
+ </object>
+ </value>
+ <value>
+ <object type="org.exoplatform.ws.frameworks.cometd.loadbalancer.Node">
+ <field name="id">
+ <string>2</string>
+ </field>
+ <field name="url">
+ <string>http://localhost:8081</string>
+ </field>
+ <field name="maxConnection">
+ <int>15</int>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+</init-params>
+ </component>
+</configuration></programlisting>
+
+ <para>The test: At testing running two servlet-containers Tomcat (in role
+ Exo - server'a) and Jetty (cometd server). A configuration example:</para>
+
+ <programlisting><configuration clients="12" repeat="1" sleep-connection="500" sleep-sending="200">
+ <container containerStart="false" port="8080" home=""/>
+ <messages>
+ <message broadcast="false" id="1">hello</message>
+ <message broadcast="true" id="2">hello!!!</message>
+ </messages>
+ <cometd-url>http://localhost:8080/cometd/cometd</cometd-url>
+ <base-url>http://localhost:8080/rest/</base-url>
+ <channels>
+ <channel>/eXo/comedt/test</channel>
+ </channels>
+</configuration></programlisting>
+
+ <para>configuration describe that we create 12 cometd connections with
+ sleep-connection = "500" (мс), will be subscribe on the channel
+ "/eXo/comedt/test". Then it will be sent two message "hello" "hello!!!"
+ the First individually to each of the clients, the second broadcast on the
+ channel. Messages delivered with an interval sleep-sending = "200". <link
+ linkend="???">http://localhost:8080/rest/</link> - base URL of Exo -
+ server. For start test execute a command:</para>
+
+ <programlisting>mvn clean install -f pom-test.xml -Dexo.test.skip=false -Djetty.home = "./target/jetty"</programlisting>
+ </section>
+
+ <section>
+ <title>Bench</title>
+
+ <para>See Cometd Cluster Bench</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/cometd.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Cometd</title>
+
+ <section>
+ <title>definition</title>
+
+ <para>Comet is a World Wide Web application architecture in which a web
+ server sends data to a client program (normally a web browser)
+ asynchronously without any need for the client to explicitly request it.
+ It allows creation of event-driven web applications, enabling real-time
+ interaction which would otherwise require much more work. Though the term
+ Comet was coined in 2006, the idea is several years older, and has been
+ called various names, including server push, HTTP push, HTTP streaming,
+ Pushlets, Reverse Ajax, and others.</para>
+
+ <para>Cometd on wikipedia <link
+ linkend="???">http://en.wikipedia.org/wiki/Comet_(programming)</link>.</para>
+
+ <para>It's an implementation of the Bayeux protocol.</para>
+ </section>
+
+ <section>
+ <title>Use</title>
+
+ <para>Cometd is deployed by default with the portal (only trunk version).
+ it's composed of a service and a webapp.</para>
+
+ <para>To get access to the cometd, you need to get a key associated with
+ the login used in the portal.</para>
+
+ <programlisting>public String getUserToken(String eXoId)</programlisting>
+
+ <para>The connection has to be initialized, for doing so you can use the
+ cometd widget available by default in the portal.</para>
+
+ <para>to send a message from the service to a user :</para>
+
+ <programlisting>public void sendMessage(String eXoId, String channel, Object data)</programlisting>
+ </section>
+
+ <section>
+ <title>Sample</title>
+
+ <para>you can find a sample here <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/portal/trunk/samp...</link></para>
+
+ <para><command>To have it working :</command></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>deploy a trunk version of the portal</para>
+ </listitem>
+
+ <listitem>
+ <para>go to ~/java/portal/trunk/sample/application/cometd/ and execute
+ exoproject --deploy=module</para>
+ </listitem>
+
+ <listitem>
+ <para>start the portal</para>
+ </listitem>
+
+ <listitem>
+ <para>load all the widgets and portlets</para>
+ </listitem>
+
+ <listitem>
+ <para>in a page, add the cometd widget and the portlet
+ "CometdDemo"</para>
+ </listitem>
+
+ <listitem>
+ <para>in the widget click on init</para>
+ </listitem>
+
+ <listitem>
+ <para>in the CometdDemo portlet, type a message and click on "send", a
+ pop up with your message will appear on the top right and disappear
+ after 3 sec</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><command>What happened?</command></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the portlet (JSR 286) sent an action with the message.</para>
+ </listitem>
+
+ <listitem>
+ <para>the action called the continuation service and sent the message
+ to the user that had sent it</para>
+ </listitem>
+
+ <listitem>
+ <para>the service sent the message to the browser</para>
+ </listitem>
+
+ <listitem>
+ <para>the cometd client side received the message, and sent it to
+ topics</para>
+ </listitem>
+
+ <listitem>
+ <para>in topic, the notification window listened to the topic
+ "/eXo/portal/notification" so the notification window appeared.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>improvements</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>replace the token system by oAuth would probably be good. not
+ sure of how it is possible.</para>
+ </listitem>
+
+ <listitem>
+ <para>There is no method yet to broadcast a message on a channel to
+ all the subscribers</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0-1.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>eXo WS 2.0.1 Release Notes (released on 2009.04.16)</title>
+
+ <section>
+ <title>Notable Changes</title>
+
+ <para>Add supports for javax.ws.rs.core.Application. It is back compatible
+ feature.</para>
+ </section>
+
+ <section>
+ <title>API changes</title>
+
+ <para>None.</para>
+ </section>
+
+ <section>
+ <title>Dependencies changed</title>
+
+ <para>Use eXo Kernel version 2.1.1</para>
+
+ <para>Use eXo Core version 2.2.1</para>
+ </section>
+
+ <section>
+ <title>How to upgrade</title>
+
+ <para>It depends on kernel 2.1.1, core 2.2.1.</para>
+ </section>
+
+ <section>
+ <title>System Requirements</title>
+
+ <para>JVM: version 1.5.x</para>
+
+ <para>Building Tools: Maven 2.0.6 and up</para>
+ </section>
+
+ <section>
+ <title>Detailed Changelog</title>
+
+ <para>Complete list of issues fixed in eXo-Ws Version 2.0.1 . Find details
+ on JIRA <link
+ linkend="???">http://jira.exoplatform.org/secure/ReleaseNote.jspa?version=10631&sty...</link>.</para>
+
+ <programlisting>Bug
+* [WS-125] - net.oauth wrong artifact id declared in maven dependencies
+* [WS-137] - Error of processing the request with encoded in UTF-8 content by gadgets.io
+* [WS-146] - In HierarchicalProperty class missing check QName.getPrefix() for length is 0
+* [WS-159] - Need add charSet for Reader and Writer in JSON transformers, problem come in in Windows OS.
+* [WS-165] - Incorrect maven dependency on net.oauth:net.oauth.core:20080229
+* [WS-166] - Generated files commited in svn
+* [WS-177] - Connection problem with NTLM when trying to connect two users in same time
+* [WS-183] - Use parent pom 1.1.1 in trunk
+
+Improvement
+* [WS-138] - Add supports for javax.ws.rs.core.Application in RESTful framework
+
+New Feature
+* [WS-176] - Create filter for URL rewriting
+* [WS-182] - Create new simple Deploy Service method with JaxWsProxyFactoryBean
+
+Task
+* [WS-168] - Change URL format of groovy services to "/{command}/{repostory}/{workspace}/{path}"
+* [WS-170] - oAuth in gadgets. Get protected resource from gadgets.
+* [WS-171] - Migrate module configuration to use kernel_1_0.xsd
+* [WS-172] - Remove unnecessary configuration from all the JARs' configuration.xml
+* [WS-184] - Release WS-2.0.1</programlisting>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/exo-ws-2-0.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>eXo WS 2.0 Release Notes (released on 2009.02.07)</title>
+
+ <section>
+ <title>Notable Changes</title>
+
+ <para>REST framework based on JSR-311 specification including:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Support of JSR-311 annotations</para>
+ </listitem>
+
+ <listitem>
+ <para>Support all media types specified in section 4.2.4 Standard
+ Entity Providers of jaxrs-1.0-final specification. Additional support
+ for 'multipart/*' and 'application/json' media types.</para>
+ </listitem>
+
+ <listitem>
+ <para>WADL generation on receipt an OPTIONS request</para>
+ </listitem>
+
+ <listitem>
+ <para>Addition feature request and response filters. Filters is
+ similar to servlet filter and gives possibility to modify request and
+ response</para>
+ </listitem>
+
+ <listitem>
+ <para>Support for RESTful services that made in Groovy.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>OAuth implementation able to use persistent storage for
+ 'tickets'</para>
+ </section>
+
+ <section>
+ <title>API changes</title>
+
+ <para>RESTful services MUST use JAX-RS annotations..</para>
+ </section>
+
+ <section>
+ <title>Dependencies changed</title>
+
+ <para>Use eXo Kernel version 2.1</para>
+
+ <para>Use eXo Core version 2.2</para>
+
+ <para>Use maven-ant-run-plugin version 1.3 instead 1.2-SNAPSHOT</para>
+
+ <para>Use jcifs version 1.2.19 instead 1.2.17</para>
+ </section>
+
+ <section>
+ <title>How to upgrade</title>
+
+ <para>See REST Migration to jsr311</para>
+ </section>
+
+ <section>
+ <title>System Requirements</title>
+
+ <para>JVM: version 1.5.x</para>
+
+ <para>Building Tools: Maven 2.0.6 and up</para>
+ </section>
+
+ <section>
+ <title>Detailed Changelog</title>
+
+ <para>Complete list of issues fixed in eXo-Ws Version 2.0. Find details on
+ <link
+ linkend="???">http://jira.exoplatform.org/secure/ReleaseNote.jspa?version=10432&sty...</link></para>
+
+ <programlisting>Bug
+* [WS-124] - Usage of SNAPSHOT in maven dependencies
+* [WS-126] - jcifs 1.2.17 is not available in public maven repo, but 1.2.19 is.
+* [WS-127] - wrong groupId for catalina dependency declaration
+
+
+Improvement
+* [WS-69] - oAuth should be able to use with annotation JSR250.
+* [WS-74] - Add possibility transfer large data (files) via org.exoplatform.services.rest.impl.provider.MultipartFormDataEntityProvider
+* [WS-77] - Check if the class org.exoplatform.ws.rest.ejbconnector30.RestEJBConnector can better handle the Portal Container to be compatible with multiple portal instance
+* [WS-78] - Check if the class org.exoplatform.ws.rest.ejbconnector21.RestEJBConnectorBean can better handle the Portal Container to be compatible with multiple portal instance
+* [WS-97] - Add support for X-HTTP-Method-Override header
+* [WS-98] - Use URI pattern for request and response filters.
+
+
+Task
+* [WS-57] - Refactor eXo REST engine to compatibility with JSR-311.
+* [WS-68] - Refactor REST EJB conector according to new implementation of REST engine (JSR-311). See WS-57.
+* [WS-75] - Add WADL generation for request with OPTIONS HTTP method.
+* [WS-81] - Change cometd service for JSR-311
+* [WS-92] - Pre-release testing plan for QA team
+* [WS-93] - Move webdav methods to the package org.exoplatform.services.rest.ext.method.webdav
+* [WS-94] - More description of classes' purpose in rest.ext sources
+* [WS-95] - Remove StandaloneContainerInitializedListener from JCR (one from WS has to be used everywhere), move PortalContainerInitializedFilter from JCR to WS
+* [WS-117] - jsr-311 capability tests
+
+Sub-task
+* [WS-101] - Create service for administration groovy scripts for REST via HTTP.
+* [WS-116] - Merge code to the branches/2.0</programlisting>
+ </section>
+
+ <section>
+ <title>Download</title>
+
+ <para>Sources: <link
+ linkend="???">http://download.forge.objectweb.org/exoplatform/exo-ws-2.0-src.zip</link></para>
+
+ <para>Demo: <link
+ linkend="???">http://download.forge.objectweb.org/exoplatform/exo-ws-2.0-tomcat.zip</link></para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/framework-for-cross-domain-ajax.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Framework for cross-domain AJAX</title>
+
+ <para>(<link
+ linkend="???">http://svn.exoplatform.org/projects/ws/branches/1.3/frameworks/cross-doma...</link>)</para>
+
+ <section>
+ <title>Motivation</title>
+
+ <para>XmlHttpRequest objects are bound by the same origin security policy
+ of browsers, which prevents a page from accessing data from another
+ server. This has put a serious limitation on Ajax developers: you can use
+ XmlHttpRequests to make background calls to a server, but it has to be the
+ same server that served up the current page. For detail's you can visit
+ <link
+ linkend="???">http://www.mozilla.org/projects/security/components/same-origin.html</link>.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ajax.gif" />
+ </imageobject>
+ </mediaobject>
+
+ <para>But actually writing client web applications that use this object
+ can be tricky given restrictions imposed by web browsers on network
+ connections across domains. So need find way how to bypass this limitation
+ of AJAX.</para>
+ </section>
+
+ <section>
+ <title>Scheme (how it works)</title>
+
+ <para>To describe our method for cross-domain AJAX solution let us
+ consider the following scheme contains of 3 components:</para>
+
+ <para>1). User agent (a browser).</para>
+
+ <para>2). ServerA contains a main page with dedicated client and server
+ IFRAMEs (see below) and an HTML client page (client.html) referenced from
+ the client IFRAME. This client page contains dedicated script to push the
+ data for request into server IFRAME.</para>
+
+ <para>3). ServerB contains remote service that want get access to and an
+ HTML server page (server.html) referenced from the server IFRAME. This
+ server page contains dedicated script to push the requested data into
+ client IFRAME.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ajax-how-it-works.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>A Working Sequence:</title>
+
+ <para>1) A Browser requests the Start page from the ServerA</para>
+
+ <para>2) The Start page is retrieved from the ServerA.</para>
+
+ <para>3) Create in the start page IFRAME (name it - "client iframe") and
+ insert on it document from ServerA (client.</para>
+
+ <para>4) In "client iframe" create ne IFRAME element ("server iframe") and
+ insert on it document from ServerB (server.html). Documents (client.html
+ and server.html) contain special script that can transfer data between
+ ifarmes.</para>
+
+ <para>5) "Client iframe" transfer information about HTTP method and URL
+ that we want do cross-domain request to "server iframe".</para>
+
+ <para>6) "Server iframe" do simple XmlHttpRequest to the service that we
+ need (it can do that because download from same domain) and get informaton
+ from service.</para>
+
+ <para>7) "Server iframe" transfer data to "client iframe" and now we get
+ information that we want.</para>
+ </section>
+
+ <section>
+ <title>How to use it</title>
+
+ <para>1). Place the file client.html and xda.js on the serverA.</para>
+
+ <para>2). Place the file server.html on the serverB.</para>
+
+ <para>3). Declare xda.js in the main page.</para>
+
+ <programlisting><script type="text/javascript" src="xda.js"></script></programlisting>
+
+ <para>4). Create JS function which performing cross domain call as in
+ following example:</para>
+
+ <programlisting><script type="text/javascript">
+ function test(){
+ var facade = xdaInit();
+ facade.clientURI = "http://localhost/cross-domain-ajax/client/client.html";
+ facade.serverURI = "http://localhost:8080/cross-domain-ajax/server/server.html";
+ facade.apiURI = "http://localhost:8080/cross-domain-ajax/server/test.txt";
+ facade.method = "POST";
+ facade.load = function(result) {
+ alert(result.responseText);
+ }
+ facade.setRequestHeader("keep-alive","200");
+ xda.create(facade);
+ }
+</script></programlisting>
+
+ <para>5). Use this function (here it is bound to a button's onclick
+ event).</para>
+
+ <programlisting><button onclick='test()'>test cross-domain</button></programlisting>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/groovy-scripts-as-rest-services.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Groovy Scripts as REST Services</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>This article describes how to use Groovy scripts as REST services.
+ We are going to consider these operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Load script and save it in JCR.</para>
+ </listitem>
+
+ <listitem>
+ <para>Instantiate script</para>
+ </listitem>
+
+ <listitem>
+ <para>Deploy newly created Class as RESTful service.</para>
+ </listitem>
+
+ <listitem>
+ <para>Script Lifecycle Management.</para>
+ </listitem>
+
+ <listitem>
+ <para>And finally we will discover simple example which can get JCR
+ node UUID</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In this article we consider RESTful service compatible with JSR-311
+ specification. Currently last feature available in version 1.11-SNAPSHOT
+ of JCR, 2.0-SNAPSHOT of WS and version 2.1.4-SNAPSHOT of core.</para>
+ </section>
+
+ <section>
+ <title>Loading script and save it in JCR</title>
+
+ <para>There are two ways to save a script in JCR. The first way is to save
+ it at server startup time by using configuration.xml and the second way is
+ to upload the script via HTTP.</para>
+
+ <para><command>Load script at startup time</command></para>
+
+ <para>This way can be used for load prepared scripts, for use this way we
+ must configure
+ org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoaderPlugin.
+ This is simple configuration example.</para>
+
+ <programlisting><external-component-plugins>
+ <target-component>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</target-component>
+ <component-plugin>
+ <name>test</name>
+ <set-method>addPlugin</set-method>
+ <type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoaderPlugin</type>
+ <init-params>
+ <value-param>
+ <name>repository</name>
+ <value>repository</value>
+ </value-param>
+ <value-param>
+ <name>workspace</name>
+ <value>production</value>
+ </value-param>
+ <value-param>
+ <name>node</name>
+ <value>/script/groovy</value>
+ </value-param>
+ <properties-param>
+ <name>JcrGroovyTest.groovy</name>
+ <property name="autoload" value="true" />
+ <property name="path" value="file:/home/andrew/JcrGroovyTest.groovy" />
+ </properties-param>
+ </init-params>
+ </component-plugin>
+</external-component-plugins></programlisting>
+
+ <para>First value-param sets JCR repository, second value-param sets
+ workspace and third one sets JCR node where scripts from plugin will be
+ stored. If specified node does not exists then it will be created. List of
+ scripts is set by properties-params. Name of each properties-param will be
+ used as node name for stored script, property autoload says to deploy this
+ script at startup time, property path sets the source of script to be
+ loaded. In this example we try to load single script from local file
+ /home/andrew/JcrGroovyTest.groovy.</para>
+
+ <para><command>Load script via HTTP</command></para>
+
+ <para>This is samples of HTTP requests. In this examples we will upload
+ script from file with name test.groovy.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-H 'Content-type:script/groovy' \
+--data-binary @test.groovy \
+http://localhost:8080/rest/script/groovy/add/repository/production/script/groovy/test.groovy</programlisting>
+
+ <para>This example imitate sending data with HTML form
+ ('multipart/form-data'). Parameter autoload is optional. If parameter
+ autoload=true then script will be instantiate and deploy script
+ immediately.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-F "file=(a)test.groovy;name=test" \
+-F "autoload=true" \
+http://localhost:8080/rest/script/groovy/add/repository/production/script/groovy/test1.groovy</programlisting>
+ </section>
+
+ <section>
+ <title>Instantiation</title>
+
+ <para>org.exoplatform.services.script.groovy.GroovyScriptInstantiator is
+ part of project exo.core.component.script.groovy. GroovyScriptInstantiator
+ can load script from specified URL and parse stream that contains Groovy
+ source code. It has possibility inject component from Container in Groovy
+ Class constructor. Configuration example:</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.services.script.groovy.GroovyScriptInstantiator</type>
+</component></programlisting>
+ </section>
+
+ <section>
+ <title>Deploy newly created Class as RESTful service</title>
+
+ <para>For deploy script automatically at server statup time its property
+ exo:autoload must be set as true.
+ org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader
+ check JCR workspaces which were specified in configuration and deploy all
+ auto-loadable scripts.</para>
+
+ <para>Example of configuration.</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</type>
+ <init-params>
+ <object-param>
+ <name>observation.config</name>
+ <object type="org.exoplatform.services.jcr.ext.script.groovy.ObservationListenerConfiguration">
+ <field name="repository">
+ <string>repository</string>
+ </field>
+ <field name="workspaces">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>production</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>In example above JCR workspace "production" will be checked for
+ autoload scripts. At once this workspace will be listened for changes
+ script's source code (property jcr:data).</para>
+ </section>
+
+ <section>
+ <title>Script Lifecycle Management</title>
+
+ <para>If GroovyScript2RestLoader configured as was decribed in previous
+ section then all "autoload" scripts deployed. In first section we added
+ script from file /home/andrew/JcrGroovyTest.groovy to JCR node
+ /script/groovy/JcrGroovyTest.groovy, repository repository, workspace
+ production. In section "Load script via HTTP" it was refered about load
+ scripts via HTTP, there is an opportunity to manage the life cycle of
+ script.</para>
+
+ <para>Undeploy script, which is alredy deployed:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy?state=false</programlisting>
+
+ <para>Then deploy it again:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy?state=true</programlisting>
+
+ <para>or even more simple:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/load/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Disable scripts autoloading, NOTE it does not change current
+ state:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/repository/production/script/groovy/JcrGroovyTest.groovy/autoload?state=false</programlisting>
+
+ <para>Enable it again:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/autoload/repository/production/script/groovy/JcrGroovyTest.groovy?state=true</programlisting>
+
+ <para>and again more simpe variant:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/autoload/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Change script source code:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-H 'Content-type:script/groovy' \
+--data-binary @JcrGroovyTest.groovy \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>This example imitate sending data with HTML form
+ ('multipart/form-data').</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+-F "file=(a)JcrGroovyTest.groovy;name=test" \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Remove script from JCR:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X GET \
+http://localhost:8080/rest/script/groovy/delete/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+ </section>
+
+ <section>
+ <title>Get node UUID example</title>
+
+ <para>Now we are going to try simple example of Groovy RESTfull service.
+ There is one limitation, even if we use groovy we should use Java style
+ code and decline to use dynamic types, but of course we can use it in
+ private methods and feilds. Create file JcrGroovyTest.groovy, in this
+ example I save it in my home directory /home/andrew/JcrGroovyTest.groovy.
+ Then configure GroovyScript2RestLoaderPlugin as described in section Load
+ script at startup time.</para>
+
+ <programlisting>import javax.jcr.Node
+import javax.jcr.Session
+import javax.ws.rs.GET
+import javax.ws.rs.Path
+import javax.ws.rs.PathParam
+import org.exoplatform.services.jcr.RepositoryService
+import org.exoplatform.services.jcr.ext.app.ThreadLocalSessionProviderService
+
+@Path("groovy/test/{repository}/{workspace}")
+public class JcrGroovyTest {
+ private RepositoryService repositoryService
+ private ThreadLocalSessionProviderService sessionProviderService
+
+ public JcrGroovyTest(RepositoryService repositoryService,
+ ThreadLocalSessionProviderService sessionProviderService) {
+ this.repositoryService = repositoryService
+ this.sessionProviderService = sessionProviderService
+ }
+
+
+ @GET
+ @Path("{path:.*}")
+ public String nodeUUID(@PathParam("repository") String repository,
+ @PathParam("workspace") String workspace,
+ @PathParam("path") String path) {
+ Session ses = null
+ try {
+ ses = sessionProviderService.getSessionProvider(null).getSession(workspace, repositoryService.getRepository(repository))
+ Node node = (Node) ses.getItem("/" + path)
+ return node.getUUID() + "\n"
+ } finally {
+ if (ses != null)
+ ses.logout()
+ }
+ }</programlisting>
+
+ <para>After configuration is done start server. If configuration is
+ correct and script does not have syntax error you should see next:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console1.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>In screenshot we can see service deployed.</para>
+
+ <para>First create folder via WebDAV in repository production, folder name
+ 'test'. Now we can try access this service. Open another console and type
+ command:</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/groovy/test/repository/production/test</programlisting>
+
+ <para>Whe you try to execute this command you should have exception,
+ because JCR node '/test' is not referenceable and has not UUID. We can try
+ add mixin mix:referenceable. To do this add one more method in script.
+ Open script from local source code /home/andrew/JcrGroovyTest.groovy, add
+ following code and save file.</para>
+
+ <programlisting>@POST
+@Path("{path:.*}")
+public void addReferenceableMixin(@PathParam("repository") String repository,
+ @PathParam("workspace") String workspace,
+ @PathParam("path") String path) {
+ Session ses = null
+ try {
+ ses = sessionProviderService.getSessionProvider(null).getSession(workspace, repositoryService.getRepository(repository))
+ Node node = (Node) ses.getItem("/" + path)
+ node.addMixin("mix:referenceable")
+ ses.save()
+ } finally {
+ if (ses != null)
+ ses.logout()
+ }
+}</programlisting>
+
+ <para>Now we can try to change script deployed on the server without
+ server restart. Type in console next command:</para>
+
+ <programlisting>andrew@ossl:~> curl -i -v -u root:exo \
+-X POST \
+--data-binary @JcrGroovyTest.groovy \
+-H 'Content-type:script/groovy' \
+http://localhost:8080/rest/script/groovy/update/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <para>Node '/script/groovy/JcrGroovyTest.groovy' has property
+ exo:autoload=true so script will be re-deployed automatically when script
+ source code changed.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console2.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Script was redeployed, now try access newly created method.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+-X POST \
+http://localhost:8080/rest/groovy/test/repository/production/test</programlisting>
+
+ <para>Method excution should be quiet, without output, traces, etc. Then
+ we can try again get node UUID.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/groovy/test/repository/production/test
+1b8c88d37f0000020084433d3af4941f</programlisting>
+
+ <para>Node UUID: 1b8c88d37f0000020084433d3af4941f</para>
+
+ <para>We don't need this scripts any more, so remove it from JCR.</para>
+
+ <programlisting>andrew@ossl:~> curl -u root:exo \
+http://localhost:8080/rest/script/groovy/delete/repository/production/script/groovy/JcrGroovyTest.groovy</programlisting>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/groovy-console3.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Groovy script restrictions</title>
+
+ <para>You should keep one class per one groovy file. The same actually for
+ interface and it implementation. It's limitation of groovy parser that
+ does not have type Class[] parseClass(InputStream) or Collection
+ parseClass(InputStream) but only Class parseClass(InputStream)
+ instead.</para>
+
+ <para>That is all.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Introduction to the Representational State Transfer (REST)</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para><command>Representational State Transfer (REST)</command> is a style
+ of software architecture for distributed hypermedia systems such as the
+ World Wide Web. The term was introduced in the doctoral dissertation in
+ 2000 by Roy Fielding, one of the principal authors of the Hypertext
+ Transfer Protocol (HTTP) specification, and has come into widespread use
+ in the networking community.</para>
+
+ <para>REST strictly refers to a collection of network architecture
+ principles that outline how resources are defined and addressed. The term
+ is often used in a looser sense to describe any simple interface that
+ transmits domain-specific data over HTTP without an additional messaging
+ layer such as SOAP or session tracking via HTTP cookies.</para>
+
+ <para>The key abstraction of information in REST is a
+ <command>resource</command>. Any information that can be named can be a
+ resource: a document or image, a temporal service (e.g. "today's weather
+ in Los Angeles"), a collection of other resources, a non-virtual object
+ (e.g. a person), and so on. In other words, any concept that might be the
+ target of an author's hypertext reference must fit within the definition
+ of a resource. A resource is a conceptual mapping to a set of entities,
+ not the entity that corresponds to the mapping at any particular point in
+ time.</para>
+
+ <para>REST uses a <command>resource identifier </command>to identify the
+ particular resource involved in an interaction between components. REST
+ connectors provide a generic interface for accessing and manipulating the
+ value set of a resource, regardless of how the membership function is
+ defined or the type of software that is handling the request. URL or URN
+ are the examples of a resource identifier.</para>
+
+ <para>REST components perform actions with a resource by using a
+ <command>representation</command> to capture the current or intended state
+ of that resource and transferring that representation between components.
+ A representation is a sequence of bytes, plus <command>representation
+ metadata </command>to describe those bytes. Other commonly used but less
+ precise names for a representation include: <command>document, file, and
+ HTTP message entity, instance, or variant</command>. A representation
+ consists of data, metadata describing the data, and, on occasion, metadata
+ to describe the metadata (usually for the purpose of verifying message
+ integrity). Metadata are in the form of name-value pairs, where the name
+ corresponds to a standard that defines the value's structure and
+ semantics. The data format of a representation is known as a media
+ type.</para>
+
+ <table>
+ <title>REST Data Elements</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Data Element</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>resource</entry>
+
+ <entry>the intended conceptual target of a hypertext
+ reference</entry>
+ </row>
+
+ <row>
+ <entry>resource identifier</entry>
+
+ <entry>URL, URN</entry>
+ </row>
+
+ <row>
+ <entry>representation</entry>
+
+ <entry>HTML document, JPEG image</entry>
+ </row>
+
+ <row>
+ <entry>representation metadata</entry>
+
+ <entry>media type, last-modified time</entry>
+ </row>
+
+ <row>
+ <entry>resource metadata</entry>
+
+ <entry>source link, alternates, vary</entry>
+ </row>
+
+ <row>
+ <entry>control data</entry>
+
+ <entry>if-modified-since, cache-control</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>REST uses various <command>connector</command> types to encapsulate
+ the activities of accessing resources and transferring resource
+ representations. The connectors present an abstract interface for
+ component communication, enhancing simplicity by providing a complete
+ separation of concepts and hiding the underlying implementation of
+ resources and communication mechanisms.</para>
+
+ <table>
+ <title>REST Connectors</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Connector</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>client</entry>
+
+ <entry>libwww, libwww-perl</entry>
+ </row>
+
+ <row>
+ <entry>server</entry>
+
+ <entry>libwww, Apache API, NSAPI</entry>
+ </row>
+
+ <row>
+ <entry>cache</entry>
+
+ <entry>browser cache, Akamai cache network</entry>
+ </row>
+
+ <row>
+ <entry>resolver</entry>
+
+ <entry>bind (DNS lookup library)</entry>
+ </row>
+
+ <row>
+ <entry>tunnel</entry>
+
+ <entry><para></para>SOCKS, SSL after HTTP CONNECT</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>The primary connector types are client and server. The essential
+ difference between the two is that a client initiates communication by
+ making a request, whereas a server listens for connections and responds to
+ requests in order to supply access to its services. A component may
+ include both client and server connectors.</para>
+
+ <para>An important part of RESTful architecture is a well-defined
+ interface to communicate, in particular it is a set of HTTP methods such
+ as POST, GET, PUT and DELETE. These methods are often compared with the
+ CREATE, READ, UPDATE, DELETE (CRUD) operations associated with database
+ technologies. An analogy can also be made:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>PUT is analogous to CREATE or PASTE OVER,</para>
+ </listitem>
+
+ <listitem>
+ <para>GET to READ or COPY,</para>
+ </listitem>
+
+ <listitem>
+ <para>POST to UPDATE or PASTE AFTER, and</para>
+ </listitem>
+
+ <listitem>
+ <para>DELETE to DELETE or CUT.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><command>Note</command>: RESTful architecture is not limited to
+ those methods, one of good examples of extension is the WebDAV
+ protocol.</para>
+
+ <para>The <command>CRUD</command> (Create, Read, Update and Delete) verbs
+ are designed to operate with atomic data within the context of a database
+ transaction. REST is designed around the atomic transfer of a more complex
+ state and can be viewed as a mechanism for transferring structured
+ information from one application to another.</para>
+
+ <para>HTTP separates the notions of a web server and a web browser. This
+ allows the implementation of each to vary from the other based on the
+ client/server principle. When used RESTfully, HTTP is
+ <command>stateless</command>. Each message contains all the information
+ necessary to understand the request.</para>
+
+ <para>As a result, neither the client nor the server needs to remember any
+ communication-state between messages. Any state retained by the server
+ must be modeled as a resource..</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/javascript-webdav-library.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,358 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>JavaScript WebDAV Library</title>
+
+ <section>
+ <title>Introduction to the JavaScript WebDAV library</title>
+
+ <para>I am proud to introduce JavaScript WebDAV library webdav.js which
+ based on AJAX. This library consists the special class webdav which is
+ aimed to make all requests supported by eXo Platform WebDAV-server with
+ supported parameters.</para>
+
+ <para>Proposed library supports asynchronous (on default) and synchronous
+ mode of AJAX request processing. To set one of some of this mode you
+ should call webdav.setAsynchronous() or webdav.setSynchronous()
+ method.</para>
+
+ <para>Also this library can fulfill BASIC HTTP authentication using value
+ of preset webdav.username and webdav.password properties.</para>
+
+ <para>Scheme of WebDAV data exchange:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/javascript-webdav.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Content of JavaScript WebDAV Library:</title>
+
+ <para>There is a list of realized methods:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>ExtensionMethod(handler, path, options) method - a simple
+ constructor of the user-defined WebDAV request.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>1. WebDAV Modifications to HTTP Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>GET(handler, path, options) method - retrieves the content of a
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>PUT(handler, path, options) method - saves the content of a
+ resource to the server.</para>
+ </listitem>
+
+ <listitem>
+ <para>DELETE(handler, path, options) method - removes a resource or
+ collection.</para>
+ </listitem>
+
+ <listitem>
+ <para>OPTIONS(handler, path, options) method - returns the HTTP
+ methods that the server supports for specified URL.</para>
+ </listitem>
+
+ <listitem>
+ <para>MKCOL(handler, path, options) method - creates a
+ collection.</para>
+ </listitem>
+
+ <listitem>
+ <para>COPY(handler, path, options) method - copies a resource from one
+ URI to another.</para>
+ </listitem>
+
+ <listitem>
+ <para>MOVE(handler, path, options) method - moves a resource from one
+ URI to another.</para>
+ </listitem>
+
+ <listitem>
+ <para>HEAD(handler, path, options) method - asks for the response
+ identical to the one that would correspond to a HEAD request, but
+ without the response body. This is useful for retrieving
+ meta-information written in response headers, without having to
+ transport the entire content.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>2. WebDAV Property Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>PROPFIND(handler, path, options) method - retrieves properties,
+ stored as XML, from a resource. It is also overloaded to allow one to
+ retrieve the collection structure (a.k.a. directory hierarchy) of a
+ remote system.</para>
+ </listitem>
+
+ <listitem>
+ <para>PROPPATCH(handler, path, options) method - changes and deletes
+ multiple properties on a resource in a single atomic act.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>3. WebDAV Lock Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>LOCK(handler, path, options) method - puts a lock on a
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>UNLOCK(handler, path, options) method - removes a lock from a
+ resource.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>4. WebDAV Versioning Extension Operations:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>VERSIONCONTROL(handler, path, options) method - is used to
+ create a new version-controlled resource for an existing version
+ history. This allows the creation of version-controlled resources for
+ the same version history in multiple workspaces.</para>
+ </listitem>
+
+ <listitem>
+ <para>CHECKOUT(handler, path, options) method - can be applied to a
+ checked-in version-controlled resource to allow modifications to the
+ content and dead properties of that version-controlled
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>CHECKIN(handler, path, options) method - can be applied to a
+ checked-out version-controlled resource to produce a new version whose
+ content and dead properties are copied from the checked-out
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>UNCHECKOUT(handler, path, options) method - can be applied to a
+ checked-out version-controlled resource to cancel the CHECKOUT and
+ restore the pre-CHECKOUT state of the version-controlled
+ resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>REPORT(handler, path, options) method - an extensible mechanism
+ for obtaining information about a resource.</para>
+ </listitem>
+
+ <listitem>
+ <para>ORDERPATCH(handler, path, options) method - is used to change
+ the ordering semantics of a collection, to change the order of the
+ collection's members in the ordering, or both.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>5. WebDAV SEARCH Operation:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>SEARCH(handler, path, options) method - a lightweight search
+ method to transport queries and result sets that allows clients to
+ make use of server-side search facilities retrieve properties, stored
+ as XML, from a resource.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If there is no interested WebDAV method in the list above, you can
+ use ExtensionMethod(handler, path, options) to construct WebDAV request
+ you like with your own:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>name of method (passing throw parameter options.method)</para>
+ </listitem>
+
+ <listitem>
+ <para>request headers (passing throw parameter options.headers)
+ and</para>
+ </listitem>
+
+ <listitem>
+ <para>request body (passing throw parameter options.body).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>First parameter of each method - hanlder - is an object {onSuccess ,
+ onError, onComplete}, which describes three functions to call when the
+ request either succeeds or fails, and completes:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>handler.onSuccess - will call if the request succeeds,</para>
+ </listitem>
+
+ <listitem>
+ <para>handler.onError - will call if the request fails,</para>
+ </listitem>
+
+ <listitem>
+ <para>handler.onComplete - will call if the request completes.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Additionally you can add your own headers to the request by using
+ the special parameter options.</para>
+
+ <para>Each method returns object result which consists next
+ properties:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>result.status - status of XMLHttp response,</para>
+ </listitem>
+
+ <listitem>
+ <para>result.statusstring - an explanation of status,</para>
+ </listitem>
+
+ <listitem>
+ <para>result.headers - object with hash of XMLHttpRequest
+ response.getAllResponseHeaders() (e.g. if this the response header is
+ "Content-Type: test/plain" then result.headers['Content-Type'] =
+ 'test/plain'),</para>
+ </listitem>
+
+ <listitem>
+ <para>result.content = XMLHttprequest response.responseXML if
+ response.header['Content-Type'] consists 'xml', or = XMLHttpRequest
+ response.responseText otherwise.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Example of using of JavaScript WebDAV library</title>
+
+ <para>An example of using WebDAV library for the eXo Platform
+ WebDAV-server:</para>
+
+ <programlisting><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Demonstration of the eXo Platform Client Library of WebDAV</title>
+ <script type="text/javascript" src="js/webdav.js"></script>
+ <script>
+
+// Example of using of eXo Platform Client Library of WebDAV
+/**
+ * Serialize an XML Document or Element and return it as a string.
+ */
+function XMLtoString(node) {
+ if (typeof node != 'object') return node;
+ if (typeof XMLSerializer != "undefined")
+ return (new XMLSerializer( )).serializeToString(node);
+ else if (node.xml) return node.xml;
+ else throw "XML.serialize is not supported or can't serialize " + node;
+};
+
+// get and setup webdav object
+ var webdav = new Webdav('localhost', '8080');
+
+ webdav.username = 'root';
+ webdav.password = 'exo';
+
+// define webdav methods handlers
+ function handler_onSuccess(result) {
+ alert('Request SUCCEEDED with status = ' + result.status + ': ' + result.statusstring);
+ };
+
+ function handler_onError(result) {
+ alert('Request FAILED with status = ' + result.status + ': ' + result.statusstring);
+ };
+
+var handler = {
+ onSuccess: handler_onSuccess,
+ onError: handler_onError,
+ onComplete: MKCOL_handler_onComplete
+}
+
+// for eXoPlatform webdav
+var default_webdav_path = '/rest/jcr/repository/collaboration';
+
+// create a collection 'test'
+webdav.MKCOL(handler, default_webdav_path + '/test1');
+
+// create a resource 'example.txt' with content 'an example'
+ function MKCOL_handler_onComplete(result) {
+ // create a resource 'example.txt' with content 'an example'
+ var options = {
+content: 'an example',
+content_type: 'text/plain; charset=UTF-8'
+ }
+ handler.onComplete = PUT_handler_onComplete;
+ webdav.PUT(handler, default_webdav_path + '/test1/example.txt', options);
+ };
+
+// put resource example.txt under version control
+ function PUT_handler_onComplete(result) {
+ // put resource example.txt under version control
+ handler.onComplete = VERSIONCONROL_handler_onComplete;
+ webdav.VERSIONCONTROL(handler, default_webdav_path + '/test1/example.txt');
+ };
+
+// obtain the 'version-tree' WebDAV report about 'example.txt'
+ function VERSIONCONROL_handler_onComplete(result) {
+ // obtain the 'version-tree' WebDAV report about 'example.txt'
+ var options = {
+ depth: '0',
+ type: 'version-tree'
+ };
+ handler.onComplete = REPORT_handler_onComplete;
+ webdav.REPORT(handler, default_webdav_path + '/test1/example.txt', options);
+ };
+
+ // delete the collection 'test'
+ function REPORT_handler_onComplete(result) {
+ if ( result.content )
+alert( 'Response of server: ' + XMLtoString(result.content) );
+
+ // delete the collection 'test'
+ handler.onComplete = 'function() {}';
+ webdav.DELETE(handler, default_webdav_path + '/test1/');
+ };
+ </script>
+</head>
+<body>
+ <h2>Demonstration of the eXo Platform Client Library of WebDAV</h2>
+</body>
+</html></programlisting>
+ </section>
+
+ <section>
+ <title>How to get JavaScript WebDAV library</title>
+
+ <para>You can get this library at the <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/branches/2.0.x...</link></para>
+
+ <para>Demonstration page was placed as <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/branches/2.0.x...</link></para>
+
+ <para>JSDoc is available at the <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/branches/2.0.x...</link></para>
+
+ <para>Another place of Javadoc will be at the <link
+ linkend="???">http://docs.exoplatform.com.ua site soon</link>.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/kerberos-sso-on-active-directory.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>Kerberos SSO on Active Directory</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>ExoPortal allows to use SSO (Single Sign On) with Kerberos
+ authentication on a Microsoft Active Directory. To install this
+ functionality, some configuration is needed, on the Active Directory
+ server and on the application server.</para>
+
+ <para>In this example, we suppose that the complete name of the machine on
+ which Tomcat server runs is ubu.exoua-int, and that it runs on the Linux
+ host (Ubuntu 7.04). This machine must be in Windows domain. How to do it
+ read in Samba documentation.</para>
+
+ <para>Our implementation makes it possible to use SPNEGO or NTLM
+ (sometimes this two terms can be mixed, but here we will try to separate
+ it). The client will get two authentication headers 'Negotiate' and 'NTLM'
+ and will use supported by client (browser). In Firefox it is possible to
+ manage authentication types, in IE this is not possible. This HOWTO will
+ describe how to make configuration to support both authentication types.
+ In fact for IE SPNEGO will work.</para>
+ </section>
+
+ <section>
+ <title>Active Directory configuration</title>
+
+ <para>On the AD server, we need to create a Kerberos identification for
+ Tomcat Server :</para>
+
+ <para>1. Create a user account for the host computer on which Tomcat
+ Server runs in the Active Directory server. (Select New > User, not New
+ > Machine.)</para>
+
+ <para>When creating the two user accounts, use the simple name of the
+ computer, and I recommend give names as next pattern host_host-name and
+ http_host-name. First account will be used for LDAP connection, second one
+ will be used for authentication service via HTTP. For example, if the host
+ name is ubu.exoua-int, create a users in Active Directory called host_ubu
+ and http_ubu.</para>
+
+ <para>Note the password you defined when creating the user account. You
+ will need it in step 3. Do not select the "User must change password at
+ next login" option, or any other password options.</para>
+
+ <para>2. Configure the new user account to comply with the Kerberos
+ protocol.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Right-click the name of the user account in the Users tree in
+ the left pane and select Properties.</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>NOTE Make sure the box "Use DES encryption types for this
+ account" is unchecked. Also make sure no other boxes are checked,
+ particularly the box "Do not require Kerberos
+ pre-authentication."</para>
+ </listitem>
+
+ <listitem>
+ <para>Setting the encryption type may corrupt the password. Therefore,
+ you should reset the user password by right-clicking the name of the
+ user account, selecting Reset Password, and re-entering the same
+ password specified earlier.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>3. Generate keys for service.</para>
+
+ <programlisting>C:\> ktpass -princ host/ubu.exoua-int@EXOUA-INT -mapuser host_ubu@EXOUA-INT -crypto RC4-HMAC-NT \
+-ptype KRB5_NT_PRINCIPAL -mapop set -pass 123456 -out c:\host_ubu.keytab
+
+
+C:\> ktpass -princ HTTP/ubu.exoua-int@EXOUA-INT -mapuser http_ubu@EXOUA-INT -crypto RC4-HMAC-NT \
+-ptype KRB5_NT_PRINCIPAL -mapop set -pass 123456 -out c:\http_ubu.keytab</programlisting>
+
+ <para>4. Use the setspn utility to create the Service Principal Names
+ (SPNs) for the user account created in step 1. Enter the following
+ commands:</para>
+
+ <programlisting>C:\> setspn -A host/ubu.exoua-int host_ubu
+C:\> setspn -A HTTP/ubu.exoua-int http_ubu</programlisting>
+
+ <para>5. Check which SPNs are associated with your user account, using the
+ following command:</para>
+
+ <programlisting>C:\> setspn -L host_ubu</programlisting>
+
+ <para>NOTE This is an important step. If the same service is linked to a
+ different account in the Active Directory server, the client will not send
+ a Kerberos ticket to the server. If filter will be used secure-constraint
+ must be removed from web.xml</para>
+
+ <para>6. Configuration on Linux host. This is example of file
+ /etc/krb5.conf</para>
+
+ <programlisting>[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+[libdefaults]
+ ticket_lifetime = 24000
+ default_realm = EXOUA-INT
+ default_tkt_enctypes = rc4-hmac
+ default_tgs_enctypes = rc4-hmac
+
+[realms]
+ EXOUA-INT = {
+ kdc = test01-srv.exoua-int:88
+ admin_server = test01-srv.exoua-int:749
+ default_domain = EXOUA-INT
+ }
+
+[domain_real]
+ .exoua-int = EXOUA-INT
+ exoua-int = EXOUA-INT
+
+[kdc]
+ profile = /etc/kdc.conf
+
+[pam]
+ debug = false
+ ticket_lifetime = 36000
+ renew_lifetime = 36000
+ forwardable = true
+ krb4_convert = false</programlisting>
+
+ <para>7. Copy key generated on step 3 to the Linux machine where tomcat
+ server runs.</para>
+
+ <para>8. Run the ktutil utility on the Linux machine and import
+ keys.</para>
+
+ <programlisting>andrew@ubu:~$ ktutil
+ktutil: rkt host_ubu.keytab
+ktutil: wkt host.keytab
+ktutil: rkt http_ubu.keytab
+ktutil: wkt http.keytab</programlisting>
+
+ <para>You must get to new files with tickets.</para>
+ </section>
+
+ <section>
+ <title>Setup webserver</title>
+
+ <para>1. Deploy an exo-tomcat, and copy the jar for SSO in lib folder and
+ change configuration.xml file to your network settings :</para>
+
+ <programlisting><configuration>
+ <component>
+ <key>org.exoplatform.services.security.sso.config.SSOConfigurator</key>
+ <type>org.exoplatform.services.security.sso.config.SSOConfigurator</type>
+ <init-params>
+ <properties-param>
+ <name>sso-properties</name>
+ <property name="charset" value="UnicodeLittleUnmarked" />
+ <property name="domain" value="EXOUA-INT" />
+ <property name="jaas-context" value="krb5.ldap-action" />
+ <property name="ldap-server" value="ldap://test01-srv.exoua-int:389/" />
+ <!--
+ **********************************************************
+ Default cross domain authentication is disabled.
+ NOTE: This is actual for NTLM only.
+ For SPNEGO cross domain authentication is disabled by default.
+ There is some more work to enable it for SPNEGO.
+ **********************************************************
+ -->
+ <!--
+ <property name="cross-domain" value="true" />
+ -->
+ <!--
+ <property name="redirect-on-error" value="http://google.com" />
+ -->
+ </properties-param>
+ </init-params>
+ </component></programlisting>
+
+ <para>2. In exo-tomcat/conf/Catalina/localhost/, change a file portal.xml
+ :</para>
+
+ <programlisting><Context path='/portal' docBase='portal' debug='0' reloadable='true' crossContext='true'>
+ <Logger className='org.apache.catalina.logger.SystemOutLogger'
+ prefix='localhost_portal_log.' suffix='.txt' timestamp='true'/>
+ <Manager className='org.apache.catalina.session.PersistentManager' saveOnRestart='false'/>
+ <!--
+ <Realm className='org.apache.catalina.realm.JAASRealm'
+ appName='exo-domain'
+ userClassNames='org.exoplatform.services.security.jaas.UserPrincipal'
+ roleClassNames='org.exoplatform.services.security.jaas.RolePrincipal'
+ debug='0' cache='false'/>
+ <Valve className='org.apache.catalina.authenticator.FormAuthenticator' characterEncoding='UTF-8'/>
+ -->
+ <Valve className="org.exoplatform.services.security.sso.tomcat.SSOAuthenticatorValve"/>
+</Context></programlisting>
+
+ <para>Secure configuration in web.xml must be changed to next:</para>
+
+ <programlisting><security-role>
+ <description>a simple user role</description>
+ <role-name>users</role-name>
+ </security-role>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>portal</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>users</role-name>
+ </auth-constraint>
+
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint></programlisting>
+
+ <para>NOTE At list one roles in web.xml must be corresponding to user
+ group in AD. </para>
+
+ <para>3. Download in lib folder jcif-1.2.17.jar . We need this for support
+ NTLM authentication. </para>
+
+ <para>4. In exo-tomcat/conf/jaas.conf, add :</para>
+
+ <programlisting>com.sun.security.jgss.accept {
+ com.sun.security.auth.module.Krb5LoginModule required
+ keyTab = "/home/andrew/http.keytab"
+ useKeyTab = true
+ storeKey = true
+ principal = "HTTP/ubu.exoua-int@EXOUA-INT"
+ doNotPrompt = true
+ realm = "EXOUA-INT"
+ refreshKrb5Config = true
+ debug = false
+ ;
+};
+
+krb5.ldap-action {
+ com.sun.security.auth.module.Krb5LoginModule required
+ keyTab = "/home/andrew/host.keytab"
+ useKeyTab = true
+ storeKey = true
+ principal = "host/ubu.exoua-int@EXOUA-INT"
+ doNotPrompt = true
+ realm = "EXOUA-INT"
+ refreshKrb5Config = true
+ debug = false
+ ;
+};</programlisting>
+
+ <para>5. Add next system properties in file bin/eXo.sh</para>
+
+ <programlisting>KERBEROS="-Djavax.security.auth.useSubjectCredsOnly=false \
+-Djava.security.krb5.kdc=test01-srv.exoua-int \
+-Djava.security.krb5.realm=EXOUA-INT"
+
+JAVA_OPTS="$YOURKIT_PROFILE_OPTION $JAVA_OPTS $LOG_OPTS $SECURITY_OPTS $EXO_OPTS $EXO_CONFIG_OPTS $KERBEROS"</programlisting>
+
+ <para>6. For portal add one more filter for initialize Identity for user
+ org.exoplatform.services.security.sso.http.JndiIdentityInitalizerFilter
+ this filter must be mapped before
+ org.exoplatform.services.security.web.SetCurrentIdentityFilter on private
+ area.</para>
+
+ <para>7. For Firefox, there is an additionnal configuration to do to use
+ AD authentication : in adress bar, go to about:config. Filter on ntlm and
+ choose "network.automatic-ntlm-auth.trusted-uris". Set string to the name
+ of the machine where webserver run (in this exemple : set "ubu"). For IE,
+ there is no additional configuration.</para>
+
+ <para>8. Go to <link
+ linkend="???">http://ubu.exoua-int:8080/portal/private/classic</link> If
+ use was login windows (domain authentication) then, Active directory
+ authentication will be used.</para>
+
+ <para>Instead tomcat valve
+ org.exoplatform.services.security.sso.tomcat.SSOAuthenticatorValve can be
+ used filter
+ org.exoplatform.services.security.sso.http.SSOAuthenticationFilter</para>
+
+ <para>9. Important about using NTLM. JCIF may use MAC for signature
+ connection to DC. In this case when one user logined, then next user may
+ be not able login during time specified in property
+ jcifs.smb.client.soTimeout (in ms), default 15000. This time JCIF keeps
+ previous connection opened and may not create new one to authenticate
+ other user. Must be set next properties to fix this
+ jcifs.smb.client.domain, jcifs.smb.client.username,
+ jcifs.smb.client.password. For example</para>
+
+ <programlisting>-Djcifs.smb.client.domain=EXOUA-INT -Djcifs.smb.client.username=Admin -Djcifs.smb.client.password=secret"</programlisting>
+
+ <para>In this case SMB connection will be signed for user.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/oauth.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>oAuth</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>OAuth allows to grant access to private resources on one site (which
+ is called the Service Provider), to another site (called Consumer). OAuth
+ is giving access to a resource without sharing your identity at all. More
+ about oAuth at the site <link linkend="???">http://oauth.net/</link>.
+ (OAuth protocol: <link
+ linkend="???">http://oauth.net/core/1.0/</link>).</para>
+
+ <para>This article describes how to configure our implementation of oAuth
+ service and client part. Both parts, service (Provider) and client
+ (Consumer) are based on oAuth core, this code can be found here <link
+ linkend="???">http://oauth.googlecode.com/svn/code/java/core/</link>.</para>
+
+ <para>Our implementation can be found here <link
+ linkend="???">http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/trunk/security...</link>.</para>
+ </section>
+
+ <section>
+ <title>Provider</title>
+
+ <para>The provider consists of two parts oauthprovider.war and
+ exo.ws.security.oauth.provider.service-trunk.jar. The main part of the
+ provider is OAuthProviderService, currently there is one implementation of
+ this interface
+ org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl; this
+ component has few required configuration parameters.</para>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>The configuration is defined in the file configuration.xml.</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl</type>
+ <init-params>
+ <properties-param>
+ <name>exo1</name>
+ <property name="secret" value="81d1b5d080d1" />
+ <property name="description" value="description" />
+ <property name="callbackURL" value="http://localhost:8080/ws-examples/callback" />
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>Properties:</para>
+
+ <para>1. <command>name</command>: the name of provider, the client will
+ send the name of provider that it wants to use.</para>
+
+ <para>2. <command>secret</command>: this property is used for subscribe
+ requests, this property must be known to the provider and the
+ consumer.</para>
+
+ <para>3. <command>description</command>: any description of the
+ provider. Optional.</para>
+
+ <para>4. <command>callbackURL</command>: this is URL where the client
+ will be redirected after successful authentication by the
+ provider.</para>
+
+ <para>That is all what is needed for the configuration of the provider
+ service. The next part of configuration is about web, such as
+ servlets.</para>
+ </section>
+
+ <section>
+ <title>Servlets</title>
+
+ <para>The web part of the provider consists of 3 servlets:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>OAuthRequestTokenServlet,</para>
+ </listitem>
+
+ <listitem>
+ <para>OAuthAccessTokenServlet, and</para>
+ </listitem>
+
+ <listitem>
+ <para>OAuthAuthorizationServlet</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+ http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <display-name>oAuth provider</display-name>
+ <context-param>
+ <description>Login page name</description>
+ <param-name>login-page</param-name>
+ <param-value>login/jsp/login.jsp</param-value>
+ </context-param>
+ <servlet>
+ <servlet-name>OAuthAuthenticationServlet</servlet-name>
+ <servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAuthenticationServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>OAuthRequestTokenServlet</servlet-name>
+ <servlet-class>org.exoplatform.ws.security.oauth.http.OAuthRequestTokenServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>OAuthAccessTokenServlet</servlet-name>
+ <servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAccessTokenServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>OAuthAuthenticationServlet</servlet-name>
+ <url-pattern>/authorize/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>OAuthRequestTokenServlet</servlet-name>
+ <url-pattern>/request_token/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>OAuthAccessTokenServlet</servlet-name>
+ <url-pattern>/access_token/*</url-pattern>
+ </servlet-mapping>
+</web-app></programlisting>
+ </section>
+ </section>
+
+ <section>
+ <title>Consumer</title>
+
+ <para>The consumer consists of OAuthConsumerService and web part (servlets
+ and filters).</para>
+
+ <section>
+ <title>How it works</title>
+
+ <para>OAuthConsumerFilter checks cookies in client's request. The cookie
+ must have the name _consumer_name_.oauth_token and
+ _consumer_name_.oauth_token_secret. Then this filter try to find the
+ request/access token this at OAuthConsumerService. If the token from the
+ request is an access token then the client is already authenticated and
+ gets access to requested resource.</para>
+
+ <para>Otherwise the client will be redirected to the provider for
+ authentication (see below, property "provider.authorizationURL"). This
+ is the part of configuration.xml for the consumer:</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.ws.security.oauth.impl.OAuthConsumerServiceImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenAliveTime</name>
+ <value>300</value>
+ </value-param>
+ <properties-param>
+ <name>exo1</name>
+ <property name="secret" value="81d1b5d080d1" />
+ <property name="description" value="description" />
+ <property name="provider.tokenRequestURL" value="http://localhost:8080/oauthprovider/request_token" />
+ <property name="provider.authorizationURL" value="http://localhost:8080/oauthprovider/authorize" />
+ <property name="provider.accessTokenURL" value="http://localhost:8080/oauthprovider/access_token" />
+ </properties-param>
+ </init-params>
+</component>
+<component>
+ <type>org.exoplatform.ws.security.oauth.impl.OAuthClientHttpImpl</type>
+</component>
+<component>
+ <type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenCleanerTimeout</name>
+ <value>3</value>
+ </value-param>
+ </init-params>
+</component></programlisting>
+
+ <para>The client is redirected for authentication to the provider with
+ the required parameters (request and secret token), before this token
+ OAuthClient got from the provider (see configuration, property
+ "provider.tokenRequestURL"). On the provider side, the user (if the
+ authentication is successful and has valid request parameters) will be
+ redirected to the consumer again (see property "callbackURL" in the
+ provider configuration). Then the consumer (this is, the same as
+ receiving request token, invisible for the client) receives the access
+ token, and redirects the client to the original URL. Then the filter
+ checks the token from the request and gives access to the requested
+ resource.</para>
+ </section>
+
+ <section>
+ <title>web.xml</title>
+
+ <para>This is the file web.xml for consumer application, in this example
+ the resource http://localhost:8080/ws-examples/oauth/protected/ is under
+ oAuth protect :</para>
+
+ <programlisting><filter>
+<filter-name>OAuthConsumerFilter</filter-name>
+ <filter-class>org.exoplatform.ws.security.oauth.http.OAuthConsumerFilter</filter-class>
+ <init-param>
+ <param-name>consumer</param-name>
+ <param-value>exo1</param-value>
+</init-param> </filter> <filter>
+<filter-name>OAuthRequestWrapperFilter</filter-name>
+<filter-class>org.exoplatform.ws.security.oauth.http.OAuthRequestWrapperFilter</filter-class> </filter>
+ <filter-mapping>
+<filter-name>OAuthConsumerFilter</filter-name>
+<url-pattern>/oauth/protected/*</url-pattern>
+</filter-mapping>
+<filter-mapping>
+<filter-name>OAuthRequestWrapperFilter</filter-name>
+<url-pattern>/oauth/protected/*</url-pattern>
+</filter-mapping></programlisting>
+
+ <para>Any resource can be protected by this mechanism under the
+ condition that web.xml is configured to use OAuthConsumerFilter. Client
+ must save the given access and the secret token in a cookie.</para>
+ </section>
+
+ <section>
+ <title>Stages</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/oauth-scheme.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>1. continuous line - client's redirections</para>
+
+ <para>2. fine dashed line - internal oAuth schema requests and
+ responses.</para>
+
+ <para>Stages:</para>
+
+ <para>1. green - stage 1 (receiving request token)</para>
+
+ <para>2. yellow - stage 2 (authentication)</para>
+
+ <para>3. blue - stage 3 (receiving access token)</para>
+
+ <para>4. red - stage 4 (get protected resource)</para>
+ </section>
+
+ <section>
+ <title>Token Alive Time</title>
+
+ <para>Alive time for tokens can be set using the parameter
+ tokenAliveTime.</para>
+
+ <programlisting><value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenAliveTime</name>
+ <value>300</value>
+</value-param></programlisting>
+ </section>
+
+ <section>
+ <title>Token Cleaner Timeout</title>
+
+ <para>There is special component cleaner on consumer side, it starts, by
+ default, every 5 minutes and checks all tokens. If it finds token with
+ expired time it removes it from the storage. Token cleaner timeout (how
+ often it must run) can be also set in the configuration:</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
+ <init-params>
+ <value-param>
+ <!-- this parameter MUST be set in minutes -->
+ <name>tokenCleanerTimeout</name>
+ <value&#623;</value>
+ </value-param>
+ </init-params>
+ </component></programlisting>
+ </section>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,472 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Framework</title>
+
+ <important>
+ <para>This describes REST framework before version exo-ws-2.0</para>
+ </important>
+
+ <section>
+ <title>Requirements</title>
+
+ <para>The purpose of eXo REST framework is to make eXo services (i.e. the
+ components deployed inside eXo Container) simple and transparently
+ accessible via HTTP in RESTful manner. In other words those services
+ should be viewed as a set of REST Resources - endpoints of the HTTP
+ request-response chain, we call those services ResourceContainers.</para>
+
+ <para>image: Simplified working model</para>
+
+ <para>Taking into account HTTP/REST constraints, it is considered that
+ Resources (naturally mapped as Java methods) contained in
+ ResourceContainer conform with the following conditions:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>they are uniquely identifiable in the same way as it is
+ specified for HTTP i.e. using URI</para>
+ </listitem>
+
+ <listitem>
+ <para>they can accept data from an HTTP request using all possible
+ mechanisms, i.e. as a part of an URL, as URI parameters, as HTTP
+ headers and body</para>
+ </listitem>
+
+ <listitem>
+ <para>they can return data to an HTTP response using all possible
+ mechanisms, i.e. as HTTP status, headers and body</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>From the implementation point of view:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the framework should be as much JSR-311 compatible as possible
+ for the time the Specification is in draft and fully compatible after
+ the standard's release</para>
+ </listitem>
+
+ <listitem>
+ <para>the ResourceContainer components should be deployable and
+ accessible in the same way as an ordinary service</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Implementation</title>
+
+ <para>In our REST architecture implementation, an HTTPServlet is the
+ front-end for the REST engine. In this RESTful framework, endpoints for
+ HTTP request are represented by java classes (ResourceContainers). All
+ ResourceContainers are run as components of an ExoContainer, so they are
+ configured within the same configuration file.</para>
+
+ <para>ResourceBinder and ResourceDispatcher are two other important
+ components of the REST engine. ResourceBinder deals with binding and
+ unbinding ResourceContainer. ResourceDispatcher dispatches REST requests
+ to ResourceContainer. ResourceBinder and ResourceDispatcher are also
+ components of the ExoContainer</para>
+
+ <section>
+ <title>ResourceContainer</title>
+
+ <para>A ResourceContainer is an annotated java class. Annotations must
+ at least describe URLs and HTTP methods to be served by this container.
+ But they may also describe other parameters, like produced content type
+ or transformers. Transformers are special Java classes, used to
+ serialize and deserialize Java objects.</para>
+
+ <para>A very simple ResourceContainer may look like this:</para>
+
+ <programlisting>@HTTPMethod("GET")
+@URITemplate("/test1/{param}/test2/")
+public Response method1(@URIParam("param") String param) {
+//...
+//...
+ Response resp = Response.Builder.ok().build();
+ return resp;
+}</programlisting>
+
+ <para>The ResourceContainer described above is very simple, it can serve
+ the GET HTTP method for the relative URL /test1/{param}/test2/ where
+ {param} can be any string value. Additionally, {param} can be used as a
+ method parameter of the container by annotating it as :
+ @URIParam("param") String param. For example, in URL /test1/myID/test2
+ the method parameter "param" has the value "myID".</para>
+
+ <para>@URITemplate may be used for annotating classes or methods. If the
+ TYPE scope annotation is for example @URITemplate("/testservices/") and
+ a METHOD scope annotation is @URITemplate("/service1/") then that method
+ can be called with the path /testservices/service1/. All
+ ResourceContainer methods return Response objects. A Response includes
+ HTTP status, an entity (the requested resource), HTTP headers and
+ OutputEntityTransformer.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>A client sends a request, after some operations, the HTTP request
+ is parsed into three parts: the HTTP request stream, which consists of
+ the body of the request, HTTP headers and query parameters. Then
+ ResourceDispatcher gets this request. During the start of ExoContainers
+ ResourceBinder collects all available ResourceContainers and after the
+ start passes the list of ResourceContainers to the ResourceDispatcher.
+ When ResourceDispatcher gets the request from a client it tries to
+ search for a valid ResourceContainer. For this search ResourceDispatcher
+ uses @HTTPMethod, @URITemplate and @ProducedMimeType annotations. The
+ last one is not always necessary, if it is not specified this is set in
+ / (all mime types). When ResourceDispatcher found the "right"
+ ResourceContainer it tries to call a method with some parameters.
+ ResourceDispatcher will send only parameters which ResourceContainer
+ requests. In the code example above the parameter is a part of the
+ requested URL between "/test1/" and "/test2/". ResourceContainer methods
+ can consist only of some well-defined parameters. See the next
+ rules:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Only one parameter of a method can be not annotated. This
+ parameter represents the body of the HTTP request.</para>
+ </listitem>
+
+ <listitem>
+ <para>All other parameters should be of java.lang.String types or
+ must have a constructor with the java.lang.String parameter and must
+ have annotation.</para>
+ </listitem>
+
+ <listitem>
+ <para>If the parameter which represents the HTTP request body is
+ present, then in the annotation @InputTransformer a java class must
+ be defined that can build the requested parameter from
+ java.io.InputStream. About transformation see below. After request
+ processing ResourceContainer creates Request. Request is a special
+ Java object which consists of HTTP status, a response header, an
+ entity, a transformer. The entity is a representation of the
+ requested resource. If Response has an entity it also must have
+ OutputEntityTransformer. OutputEntityTransformer can be set in a few
+ different ways.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Response</title>
+
+ <para>Response is created by Builder. Builder is an inner static Java
+ class within Response. Builder has some preset ways to build Response,
+ for example (see code example above). The method ok() creates Builder
+ with status 200 (OK HTTP status) and ok() returns again a Builder
+ object. In this way a developer can again call other Builder methods.
+ For example:</para>
+
+ <programlisting>//...
+Document doc = ....
+Response response = Response.Builder.ok().entity(doc, "text/xml").transformer(new XMLOutputTransformer()).build();</programlisting>
+
+ <para>In the code example above Response has HTTP status 200, an XML
+ document like entity, a Content-Type header "text/xml" and
+ OutputEntityTransformer of type XMLOutputTransformer. The method build()
+ should be called at the end of process. In the same way a developer can
+ build some other prepared Responses, like CREATED, NO CONTENT,
+ FORBIDDEN, INTERNAL ERROR and other. In this example we set
+ OutputEntityTransformer directly. Another mechanism to do this is the
+ same like in the case with InputEntityTransformer.</para>
+
+ <programlisting>//...
+@HTTPMethod("GET")
+@URITemplate("/test/resource1/")
+(a)InputTransformer(XMLInputTransformer.class)
+(a)OutputTransformer(XMLOutputTransformer.class)
+public Response method1(Document inputDoc) {
+//...
+ Document doc = ....
+ Response response = Response.Builder.ok(doc, "text/xml").build();
+ return response;
+}</programlisting>
+
+ <para>InputEntityTransformer is described in the annotation to the
+ method "method1". OutputEntityTransformer is described in the annotation
+ to the method "method1".</para>
+ </section>
+
+ <section>
+ <title>Transformer</title>
+
+ <para>All transformers can be created by EntityTransformerFactory.
+ Transformers can be divided in two groups. Transformers from the first
+ one extend the abstract class InputEntityTransformer.
+ InputEntityTransformer implements the interface
+ GenericInputEntityTransformer, and GenericInputEntityTransformer extends
+ the interface GenericEntityTransformer. This architecture gives the
+ possibility to use one class EntityTransformerFactory for creating both
+ types of transformers (input and output). At first we will speak about
+ InputEntityTransformer.</para>
+
+ <para><command>InputEntityTransformer</command></para>
+
+ <para>All classes which extend the abstract class InputEntitytransformer
+ must override the method ObjectreadFrom(InputStream entityDataStream).
+ This method must return an object with the same type as
+ ResourceContainer requires in method parameters (one not annotated
+ parameter). This mechanism works in the following way. For example, a
+ class which extends InputEntityTransformer will be called
+ SimpleInputTransformer. So, SimpleInputTransformer must have a simple
+ constructor (without any parameters). SimpleInputTransformer also has
+ two methods void setType(Class entityType) and Class getType(). Those
+ methods are described in InputEntityTransformer. And, as we said above,
+ SimpleInputTransformer must override the abstract method Object
+ readFrom(InputStream entityDataStream). So, a developer needs to create
+ a class which can build a Java Object from InputStream and then create
+ annotation to ResourceContainer or some method in ResourceContainer.
+ This annotation must define the type of InputEntityTransformer. Here is
+ the code of the annotation InputTransformer.</para>
+
+ <programlisting>//...
+@Retention(RUNTIME)
+@Target({TYPE, METHOD})
+public @interface InputTransformer {
+ Class<? extends InputEntityTransformer> value();
+}</programlisting>
+
+ <para>Then ResourceDispatcher gets InputTransformer from the factory
+ during runtime then builds an Object from stream and adds it to the
+ parameter array. See the code below.</para>
+
+ <programlisting>//...
+ InputEntityTransformer transformer = (InputEntityTransformer) factory_.newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+//...
+ Response response = (Response) resource.getServer().invoke(resource.getResourceContainer(), params);</programlisting>
+
+ <para>A developer can find some prepared transformers in the package
+ "org.exoplatform.services.rest.transformer".</para>
+
+ <para><command>OutputEntityTransformer</command></para>
+
+ <para>OutputEntityTransformer can be used to serialize the Object which
+ represents the requested resource to OutputStream.
+ OutputEntityTransformer, in future we will call it
+ SimpleOutputTransformer, can be defined in a few ways.</para>
+
+ <para>Now some more words about transformation. The RESTful framework
+ has two multi-purpose input/output transformers. One of them is
+ JAXB(Input/Output)Transformer, and another one is
+ Serializable(Input/Output)Transformer. The first one uses JAXB API for
+ serializing and deserializing an object. Serializable
+ (Input/Output)Transformer uses the own methods of an entity for
+ serialization and deserialization. Here is an example:</para>
+
+ <programlisting>/...
+public class SimpleSerializableEntity implements SerializableEntity {
+
+ String data;
+
+ public SimpleSerializableEntity() {
+ }
+
+ public void readObject(InputStream in) throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int rd = -1;
+ while((rd = in.read()) != -1)
+ sb.append((char)rd);
+ data = sb.toString();
+ }
+
+ public void writeObject(OutputStream out) throws IOException {
+ out.write(data.getBytes());
+ }
+}</programlisting>
+
+ <para>SerializableInputTransformer will try to use the method void
+ readObject(InputStream in) and SerializableOutputTransformer will try to
+ use the method void writeObject(OutputStream in).</para>
+ </section>
+
+ <section>
+ <title>Binding and unbinding components (ResourceContainers)</title>
+
+ <para>ResourceBinder takes care of binding and unbinding components
+ which represent ResourceContainer. All ResourceContainers must be
+ defined as ExoContainer components in configuration files, for
+ example:</para>
+
+ <programlisting><component>
+ <type>org.exoplatform.services.rest.samples.RESTSampleService</type>
+</component></programlisting>
+
+ <para>ResourceBinder is an ExoContainer component and implements the
+ interface org.picocontainer.Startable (see the picocontainer
+ documentation). So at the start of ExoContainer ResourceBinder collects
+ all available ResourceContainers. ResourceBinder makes validation for
+ all ResourceContainers. At least each ResourceContainer must have the
+ @HTTPMethod annotation and @URITemplate annotation. Other annotations
+ are not obligatory. It's not allowed to have few ResourceContainers or
+ methods with the same @HTTPMethod and @URITemplate annotation value. For
+ example, if one container/method has the following code:</para>
+
+ <programlisting>public class SimpleResourceContainer implements ResourceContainer {
+ @HTTPMethod("GET")
+ @URITemplate("/services/{id}/service1/")
+ @InputTransformer(StringInputTransformer.class)
+ @OutputTransformer(StringOutputTransformer.class)
+ public Response method1(String data, @URIParam("id") String param) {
+ // ...
+ }
+}</programlisting>
+
+ <para>than another component with @HTTPMethod("GET") and
+ @URITemplate("/services/service1/{id}/") can't be bound. And now we'll
+ try to explain this situation. On the one hand URITemplate is defined by
+ value /services/{id}/service1/, instead of {id} there can be any other
+ string value, so the combination /services/service1/service1/ is
+ possible and valid. On the other hand another URITemplate
+ /services/service1/{id}/ can have the string service1 instead of {id},
+ so for this resource the combination /services/service1/service1/ is
+ possible and valid. And now we have two resources with the same
+ URITemplate and the same HTTPMethod. This situation is not obligatory,
+ we can't say what method we must call! In this case ResourceBinder
+ generates InvalidResourceDescriptorException. Binder also checks the
+ method parameters. In parameters only one parameter without annotation
+ and of free type is allowed. All other parameters must have String type
+ (or have a constructor with String) and be annotated. In other cases
+ InvalidResourceDescriptorException* is generated. If all components have
+ the "right" @HTTPMethod and @URITemplate annotations they should be
+ bound without any problems. ResourceDispather gets a collection of
+ ResourceContainers during the start and everything is ready to serve a
+ request.</para>
+
+ <para>Note: within the scope of one component (one class) validation for
+ URI templates is not implemented, so a developer must take care of
+ @URITemplate and @HTTPMethod. Both of them must not be the same for
+ different methods. Except if @QueryTemplate or/and @ProducedMimeTypes
+ annotation is used.</para>
+ </section>
+
+ <section>
+ <title>ResourceDispatcher</title>
+
+ <para>Now let's talk about the features of ResourceDispatcher.
+ ResourceDispatcher is the main part of the RESTful engine. Above we said
+ some words about transformation and the role of ResourceDispatcher in
+ this process. Now we are ready to talk about annotated method
+ parameters. In one of the code examples above you could see the next
+ construction</para>
+
+ <programlisting>public Response method1(String data, @URIParam("id") String param) {</programlisting>
+
+ <para>The method method1 is described with two parameters. The first
+ parameter String data is built from the entity body (InputStream). The
+ second one - String param is annotated by a special type Annotation.
+ This Annotation has the following code:</para>
+
+ <programlisting>@Target(value={PARAMETER})
+@Retention(RUNTIME)
+public @interface URIParam {
+ String value();
+}</programlisting>
+
+ <para>How does it work? After having found the right method
+ ResourceDispatcher gets the list of method parameters and starts
+ handling them. Dispatcher tries to find the not annotated parameter
+ (this entity body) and addresses InputEntityTransformer in order to
+ build the required Object from InputStream. When dispatcher finds an
+ annotated parameter it checks the type of annotation. It is possible to
+ have four types of annotation: @URIParam, @HeaderParam, @QueryParam and
+ @ContextParameter. If dispatcher has found the annotation
+ @URIParam("id") then it takes the parameter with the key "id" from
+ ResourceDescription and adds it into the parameter array. The same
+ situation is with header, context and query parameters. So within the
+ method a developer gets only the necessary parameters from header, query
+ and uri. Some more information about @ContextParameters.
+ @ContextParameters can be set in the configuration file of a
+ component:</para>
+
+ <programlisting><component>
+<type>org.exoplatform.services.rest.ResourceDispatcher</type>
+ <init-params>
+ <properties-param>
+ <name>context-params</name>
+ <property name="test" value="test_1"/>
+ </properties-param>
+ </init-params>
+</component></programlisting>
+
+ <para>In this case any service can use this parameter, for
+ example:</para>
+
+ <programlisting>...method(@ContextParam("test") String p) {
+ System.out.println(p);
+}</programlisting>
+
+ <para>After its execution you should see "test_1" in console.</para>
+
+ <para>And in each service the next context parameters can be used. The
+ name of these parameters are described in ResourceDispatcher:</para>
+
+ <programlisting>public static final String CONTEXT_PARAM_HOST = "host";
+public static final String CONTEXT_PARAM_BASE_URI = "baseURI";
+public static final String CONTEXT_PARAM_REL_URI = "relURI";
+public static final String CONTEXT_PARAM_ABSLOCATION = "absLocation";</programlisting>
+
+ <para>After that dispatcher finishes collecting parameters that the
+ method requires, invokes this method and passes the result to the client
+ as it is described above.</para>
+
+ <para>This part of code can explain how this mechanism works:</para>
+
+ <programlisting>//...
+ for (int i = 0; i < methodParametersAnnotations.length; i++) {
+ if (methodParametersAnnotations[i] == null) {
+ InputEntityTransformer transformer = (InputEntityTransformer) factory
+ .newTransformer(resource.getInputTransformerType());
+ transformer.setType(methodParameters[i]);
+ params[i] = transformer.readFrom(request.getEntityStream());
+ } else {
+ Constructor<?> constructor = methodParameters[i].getConstructor(String.class);
+ String constructorParam = null;
+ Annotation a = methodParametersAnnotations[i];
+ if (a.annotationType().isAssignableFrom(URIParam.class)) {
+ URIParam u = (URIParam) a;
+ constructorParam = request.getResourceIdentifier().getParameters().get(u.value());
+ } else if (a.annotationType().isAssignableFrom(HeaderParam.class)) {
+ HeaderParam h = (HeaderParam) a;
+ constructorParam = request.getHeaderParams().get(h.value());
+ } else if (a.annotationType().isAssignableFrom(QueryParam.class)) {
+ QueryParam q = (QueryParam) a;
+ constructorParam = request.getQueryParams().get(q.value());
+ } else if (a.annotationType().isAssignableFrom(ContextParam.class)) {
+ ContextParam c = (ContextParam) a;
+ constructorParam = contextHolder_.get().get(c.value());
+ }
+ if (methodParameters[i].isAssignableFrom(String.class)) {
+ params[i] = constructorParam;
+ } else {
+ params[i] = (constructorParam != null) ? constructor.newInstance(constructorParam) : null;
+ }
+ }
+ }
+ Response resp = (Response) resource.getServer().invoke(resource.getResourceContainer(), params);
+//...</programlisting>
+
+ <para>The more detailed schema looks like this:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-scheme-detailed.png" />
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-migration-to-jsr311.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Migration to jsr311</title>
+
+ <important>
+ <para>The new implementation of the REST engine respects the jsr311
+ specification.</para>
+ </important>
+
+ <section>
+ <title>REST service structure:</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>REST service must be represented by Java class that has @Path
+ annotation, it calls <command>root resource</command>. In some cases
+ class may have not @Path, about this classes see in Sub-Resource
+ Locators section. Root resource class may contain <command>Resource
+ Methods</command>, <command>Sub-Resource Methods</command> and
+ <command>Sub-Resource Locators</command>. Root resource MUST contain
+ at least one of it. </para>
+
+ <para>1. <command>Resource Method</command> it is method that contains
+ HTTP method annotation, e.g. @GET, @POST, etc. and it does not contain
+ @Path annotation. </para>
+
+ <para>2. <command>Sub-Resource Method</command> it is method that
+ contains HTTP method annotation and @Path annotation. Sub-Resource
+ Locator it is method that does not contain HTTP method annotation but
+ contains @Path annotation. </para>
+
+ <para>3. <command>Sub-Resource Locator </command>can't process request
+ directly but it can produce Object (Resource) and that object can
+ process request or has <command>Sub-Resource Locator</command> that
+ can produce other Resource.Other important part @Consumes and
+ @Produces annotations. These annotations can be used at classes and
+ methods. Annotation on method override annotation on class.</para>
+ </listitem>
+
+ <listitem>
+ <para>Annotated method parameters @PathParam, @QueryParam, @FormParam,
+ @HeaderParam, @Matrix, @CookieParam, @Context annotation must be
+ (Description of this annotation in jsr311 specification or jsr311-api
+ javadoc): </para>
+
+ <para>1. String </para>
+
+ <para>2. Primitive type, except char </para>
+
+ <para>3. Has constructor with single string arguments </para>
+
+ <para>4. Has static valueOf method with single string argument </para>
+
+ <para>5. Be List, Set or SortedSet with items described in first four
+ points</para>
+ </listitem>
+
+ <listitem>
+ <para>Not annotated method parameter or <command>Entity
+ Parameter</command>. </para>
+
+ <para>1. Must be not more then one </para>
+
+ <para>2. <command>Sub-Resource Locator</command> MUST NOT have
+ <command>Entity Parameter</command>. </para>
+
+ <para>3. If <command>Resource Method</command> or
+ <command>Sub-Resource Method</command> contains at least one parameter
+ with @FormParam annotation then <command>Entity Parameter</command>
+ MUST be MultivaluedMap<String, String> only.</para>
+ </listitem>
+
+ <listitem>
+ <para>Method return type. Resource method (<command>Resource
+ Method</command> or <command>Sub-Resource Method</command>) may return
+ void,javax.ws.rs.core.Response,javax.ws.rs.core.GenericEntity or other
+ Java type. If void type returned ot returned object is null then 204
+ HTTP status will be set for response otherwise 200 status will be
+ used. With javax.ws.rs.core.Response response can be set by service
+ developer.</para>
+ </listitem>
+
+ <listitem>
+ <para>Reading/Writing Entity done via
+ <command>EntityProvider</command>. Each
+ <command>EntityProvider</command> can require precise preset media
+ type of entity, for example JsonEntityProvider require 'Content-Type'
+ and/or 'Accept' header set as application/json. REST engine supports
+ next entity provider:</para>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry align="center">Provider class</entry>
+
+ <entry align="center">Media Type</entry>
+
+ <entry align="center">Java Type</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>ByteEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>byte[]</entry>
+ </row>
+
+ <row>
+ <entry>DataSourceEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>javax.activation.DataSource</entry>
+ </row>
+
+ <row>
+ <entry>DOMSourceEntityProvider</entry>
+
+ <entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.dom.DOMSource</entry>
+ </row>
+
+ <row>
+ <entry>FileEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.File</entry>
+ </row>
+
+ <row>
+ <entry>MultivaluedMapEntityProvider</entry>
+
+ <entry>application/x-www-form-urlencoded</entry>
+
+ <entry>MultivaluedMap<String, String></entry>
+ </row>
+
+ <row>
+ <entry>MultipartFormDataEntityProvider</entry>
+
+ <entry>multipart/*</entry>
+
+ <entry>java.util.Iterator<org.apache.commons.fileupload.FileItem></entry>
+ </row>
+
+ <row>
+ <entry>InputStreamEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.InputStream</entry>
+ </row>
+
+ <row>
+ <entry>ReaderEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.io.Reader</entry>
+ </row>
+
+ <row>
+ <entry>SAXSourceEntityProvider</entry>
+
+ <entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.sax.SAXSource</entry>
+ </row>
+
+ <row>
+ <entry>StreamSourceEntityProvider</entry>
+
+ <entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.transform.stream.StreamSource</entry>
+ </row>
+
+ <row>
+ <entry>StringEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>java.lang.String</entry>
+ </row>
+
+ <row>
+ <entry>StreamOutputEntityProvider</entry>
+
+ <entry>*/*</entry>
+
+ <entry>NOTE for writing data only</entry>
+ </row>
+
+ <row>
+ <entry>JsonEntityProvider</entry>
+
+ <entry>application/json</entry>
+
+ <entry>Object (simple constructor, get/set methods)</entry>
+ </row>
+
+ <row>
+ <entry>JAXBElementEntityProvider</entry>
+
+ <entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>javax.xml.bind.JAXBElement</entry>
+ </row>
+
+ <row>
+ <entry>JAXBObjectEntityProvider</entry>
+
+ <entry>application/xml,application/xhtml+xml,text/xml</entry>
+
+ <entry>Object (simple constructor, get/set methods)</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Migration Examples</title>
+
+ <para>EXAMPLE #1</para>
+
+ <para><command>Old code</command></para>
+
+ <programlisting>package org.exoplatform.services.rest.example;
+
+import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.URIParam;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.services.rest.transformer.StringOutputTransformer;
+import org.exoplatform.services.rest.OutputTransformer;
+import org.exoplatform.services.rest.Response;
+
+@URITemplate("/a/{1}/b")
+public class Resource implements ResourceContainer {
+
+ @HTTPMethod("GET")
+ @URITemplate("{2}")
+ @OutputTransformer(StringOutputTransformer.class)
+ public Response m0(@URIParam("1") String param1, @URIParam("2") String param2) {
+ Response resp = Response.Builder.ok(param1+param2, "text/plain").build();
+ return resp;
+ }
+}</programlisting>
+
+ <para><command>New code</command></para>
+
+ <programlisting>import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam
+
+@Path("/a/{1}/b")
+public class Resource implements ResourceContainer {
+ @GET
+ @Path("{2}")
+ @Produces("text/plain")
+ public String m0(@PathParam("1") String param1, @PathParam("2") String param2) {
+ return path1+path2;
+ }
+}</programlisting>
+
+ <para>EXAMPLE #2</para>
+
+ <para><command>Old code</command></para>
+
+ <programlisting>import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.InputTransformer;
+import org.exoplatform.services.rest.Response;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.ws.frameworks.json.transformer.Json2BeanInputTransformer;
+
+public class Resource implements ResourceContainer {
+ @HTTPMethod("POST")
+ @URITemplate("/")
+ @InputTransformer(Json2BeanInputTransformer.class)
+ public Response m0(Book book) {
+ // do something with bean
+ return Response.Builder.noContent().build();
+ }
+}</programlisting>
+
+ <para><command>New code</command></para>
+
+ <programlisting>import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Consumes;
+
+@Path("/")
+public class Resource implements ResourceContainer {
+ @POST
+ @Consumes("application/json")
+ public void m0(Book book) {
+ // do something with bean
+ }
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Support for javax.ws.rs.core.Application</title>
+
+ <para>Since version exo-ws-2.0.1 add support for class
+ javax.ws.rs.core.Application. It gives possibility to setup services and
+ provider life-cycle to singleton or per-request mode. For details see
+ JAX-RS specification, chapter 2. Subclass of Application should be
+ configured as component of exo-container.</para>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>REST Service Tutorial</title>
+
+ <important>
+ <para>This article describes REST framework before version
+ exo-ws-2.0.</para>
+ </important>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This HOW-TO explains how to create your own REST based services. In
+ this HOW-TO we will create a simple calculator, which can do basic
+ operations with integers.</para>
+ </section>
+
+ <section>
+ <title>Source code</title>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+}</programlisting>
+
+ <para>Writing <command>@URITemplate</command> before the class definition
+ gives you the possibility not to set it for each method. Furthermore the
+ class must implement the interface <command>ResourceContainer</command>.
+ This interface doesn't have any methods, it is just an indication for the
+ <command>ResourceBinder</command>. Add the code for adding two
+ integers.</para>
+
+ <programlisting>// ...
+@URITemplate("/calculator/{item1}/{item2}/")
+public class Calculator implements ResourceContainer {
+ @QueryTemplate("operation=add")
+ @OutputTransformer(StringOutputTransformer.class)
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1,
+ @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" = ").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>@QueryTemplate("operation=add") - only requests with query
+ parameters "operation=add" can reach this method;
+ @OutputTransformer(StringOutputTransformer.class) - the output
+ transformer; @HTTPMethod("GET") - the HTTP method "GET".</para>
+
+ <para>Write the code for other operations in the same way. Then the result
+ should look like:</para>
+
+ <programlisting>package org.exoplatform.services.rest.example;
+
+import org.exoplatform.services.rest.HTTPMethod;
+import org.exoplatform.services.rest.OutputTransformer;
+import org.exoplatform.services.rest.QueryTemplate;
+import org.exoplatform.services.rest.Response;
+import org.exoplatform.services.rest.URIParam;
+import org.exoplatform.services.rest.URITemplate;
+import org.exoplatform.services.rest.container.ResourceContainer;
+import org.exoplatform.services.rest.transformer.StringOutputTransformer;
+
+@URITemplate("/calculator/{item1}/{item2}/")
+(a)OutputTransformer(StringOutputTransformer.class)
+public class Calculator implements ResourceContainer {
+
+ @QueryTemplate("operation=add")
+ @HTTPMethod("GET")
+ public Response add(@URIParam("item1") Integer item1, @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" + ").append(item2).append(" = ").append(item1 + item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=subtract")
+ @HTTPMethod("GET")
+ public Response subtract(@URIParam("item1") Integer item1, @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" - ").append(item2).append(" = ").append(item1 - item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=multiply")
+ @HTTPMethod("GET")
+ public Response multiply(@URIParam("item1") Integer item1, @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" * ").append(item2).append(" = ").append(item1 * item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+
+ @QueryTemplate("operation=divide")
+ @HTTPMethod("GET")
+ public Response divide(@URIParam("item1") Integer item1, @URIParam("item2") Integer item2) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(item1).append(" / ").append(item2).append(" = ").append(item1 / item2);
+ return Response.Builder.ok(sb.toString(), "text/plain").build();
+ }
+}</programlisting>
+
+ <para>So we are done with the source code.</para>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>Create the directory conf/portal and create the file
+ configuration.xml in it. Add the following code to this file:</para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration>
+ <component>
+ <type>org.exoplatform.services.rest.example.Calculator</type>
+ </component>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Build</title>
+
+ <para>Now we must create the following directory structure to get the
+ possibility to build the source code using maven.</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-build-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>Then create the file pom.xml using the following:</para>
+
+ <programlisting><project>
+ <parent>
+ <groupId>org.exoplatform.ws</groupId>
+ <artifactId>config</artifactId>
+ <version>trunk</version>
+ </parent>
+
+ <modelVersion&#624;.0.0</modelVersion>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>simple.calculator</artifactId>
+ <packaging>jar</packaging>
+ <version>trunk</version>
+ <description>Simple REST service</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.exoplatform.ws.rest</groupId>
+ <artifactId>exo.rest.core</artifactId>
+ <version>trunk</version>
+ </dependency>
+ </dependencies>
+</project></programlisting>
+
+ <para>Build this by executing the command:</para>
+
+ <programlisting>andrew@ubu:~/workspace/calculator$ mvn clean install</programlisting>
+ </section>
+
+ <section>
+ <title>Deploy</title>
+
+ <para>We have done all now. Then copy the jar file from the target
+ directory of project exo-tomcat into the server with all prepared stuff
+ for REST services. (You can download it here: <link
+ linkend="???">http://forge.objectweb.org/project/download.php?group_id=151&file_id=...</link>)</para>
+
+ <para>So just put the jar file into the lib directory of the tomcat and
+ restart it. In the console you should see this message:</para>
+
+ <programlisting>[INFO] ResourceBinder - Bind new ResourceContainer: org.exoplatform.services.rest.example.Calculator@19846fd</programlisting>
+
+ <para>This message indicates that our service was found, bound and is
+ ready to work</para>
+ </section>
+
+ <section>
+ <title>Usage</title>
+
+ <para>Open your browser and type the following URL: <link
+ linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=add</link>
+ and you should see the next page:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/rest-run-process.png" />
+ </imageobject>
+ </mediaobject>
+
+ <para>The service is working. This is a very simple example, but it should
+ help developers use the REST framework.</para>
+
+ <para>Try to check other URLs.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
+ linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=subtract</link>
+ - must give "12 - 5 = 7";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+ linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=multiply</link>
+ - must give "12 * 5 = 60";</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+ linkend="???">http://localhost:8080/rest/calculator/12/5/?operation=divide</link>-
+ must give "12 / 5 = 2" (we are working with integers!);</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Added: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml (rev 0)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws/soap-service-tutorial.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <?dbhtml filename="ch-ws.html"?>
+
+ <title>SOAP Service Tutorial</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>In this tutorial you will learn how you can use JSR 181 to expose
+ your Exo Container components as web services.</para>
+
+ <para>The steps given below have been tested with eXo WS samples 2.0.2
+ under Tomcat 6.0.16. It uses the WS tomcat bundle.</para>
+
+ <para>You can use maven build within "ws/tags/2.0.2/application" to deploy
+ this sample application configuration:</para>
+
+ <programlisting>mvn clean install -f product-exo-ws-as-tomcat6.xml antrun:run</programlisting>
+ </section>
+
+ <section>
+ <title>Add JSR 181 support to the deployed application</title>
+
+ <para>The JSR181 support does not come by default in portal.</para>
+
+ <para>The WS example tomcat bundle, which you can deploy with provided
+ command above, has already all necessary libraries and SOAP servlet
+ declarations.</para>
+
+ <para>For any other bundles you have to done the two steps below.</para>
+
+ <section>
+ <title>Add dependencies</title>
+
+ <para>First you need to add the necessary dependencies inside
+ exo-tomcat/lib</para>
+
+ <para>The required artifacts are :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>exo.ws.soap.cxf.jsr181-2.0.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>exo.ws.application.soap.cxf.samples-2.0.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-transports-http-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-api-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-core-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-common-utilities-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>wsdl4j-1.6.1.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>geronimo-jaxws_2.1_spec-1.0.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>geronimo-ws-metadata_2.0_spec-1.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-frontend-jaxws-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-frontend-simple-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-bindings-soap-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>XmlSchema-1.4.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-databinding-jaxb-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>jaxb-impl-2.1.7.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-tools-common-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>cxf-rt-ws-addr-2.1.2.jar</para>
+ </listitem>
+
+ <listitem>
+ <para>saaj-api-1.3.jar</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Configure CXF servlet</title>
+
+ <para>Edit YOUR_APPLICATION.war/WEB-INF/web.xml and add the CXF servlet
+ :</para>
+
+ <programlisting><servlet>
+ <servlet-name>SOAPServlet</servlet-name>
+ <display-name>SOAP Servlet</display-name>
+ <servlet-class>org.exoplatform.services.ws.impl.cxf.transport.http.SOAPServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>SOAPServlet</servlet-name>
+ <url-pattern>/soap/services/*</url-pattern>
+ </servlet-mapping></programlisting>
+
+ <important>
+ <para>alternatively, you could bundle cxf in a separate app, but make
+ sure ws-examples.war starts before it</para>
+ </important>
+ </section>
+ </section>
+
+ <section>
+ <title>Write the Web Service class</title>
+
+ <para>We have a tiny sample to demonstrate called :
+ TicketOrderService.</para>
+
+ <para>Following JSR 181, it is now just a matter of annotating a class to
+ create a Web Service. The main idea is the your interface has to extends
+ extends AbstractSingletonWebService.</para>
+
+ <programlisting>@WebService
+public interface TicketOrderService extends AbstractSingletonWebService {
+
+ /**
+ * @param departing departing place.
+ * @param arriving arriving place.
+ * @param departureDate departure date.
+ * @param passenger passenger.
+ * @return ticket order.
+ */
+ public String getTicket(String departing, String arriving, Date departureDate, String passenger);
+
+ /**
+ * @param confirmation confirm or not.
+ */
+ public void confirmation(boolean confirmation);
+
+}</programlisting>
+
+ <programlisting>@WebService(serviceName = "TicketOrderService",
+ portName = "TicketOrderServicePort",
+ targetNamespace = "http://exoplatform.org/soap/cxf")
+public class TicketOrderServiceImpl implements TicketOrderService {
+
+ /**
+ * Logger.
+ */
+ private static final Log LOG = ExoLogger.getLogger(TicketOrderServiceImpl.class);
+
+ /**
+ * Ticket.
+ */
+ private Ticket ticket;
+
+ /**
+ * @param departing departing place.
+ * @param arriving arriving place.
+ * @param departureDate departure date.
+ * @param passenger passenger.
+ * @return ticket order.
+ */
+ public String getTicket(String departing, String arriving, Date departureDate, String passenger) {
+ ticket = new Ticket(passenger, departing, arriving, departureDate);
+ LOG.info(ticket);
+ return String.valueOf(ticket.getOrder());
+ }
+
+ /**
+ * @param confirmation confirm or not.
+ */
+ public void confirmation(boolean confirmation) {
+ LOG.info("Confirmation : " + confirmation + " for order '" + ticket.getOrder() + "'.");
+ }
+
+}</programlisting>
+
+ <para>To test quickly, you can simply grab the jar on eXo repository and
+ deploy within your application.</para>
+ </section>
+
+ <section>
+ <title>Configure the component</title>
+
+ <programlisting><configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_0.xsd http://www.exoplatform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplatform.org/xml/ns/kernel_1_0.xsd">
+ <component>
+ <type>org.exoplatform.services.ws.soap.jsr181.TicketOrderServiceImpl</type>
+ </component>
+</configuration></programlisting>
+ </section>
+
+ <section>
+ <title>Verify it works.</title>
+
+ <para>Start server.</para>
+
+ <para>Execute script at
+ ws/tags/2.0.2/application/java/services/samples/soap/client to test
+ service</para>
+
+ <programlisting>run.sh</programlisting>
+
+ <para>and watch for this in the logs:</para>
+
+ <programlisting>Sep 3, 2009 5:21:13 PM org.apache.cxf.endpoint.ServerImpl initDestination
+INFO: Setting the server's publish address to be /TicketOrderService/TicketOrderServicePort
+03.09.2009 17:21:13 *INFO * [http-8080-1] ExoDeployCXFUtils: The webservice '/TicketOrderService/TicketOrderServicePort' has been published SUCCESSFUL! (ExoDeployCXFUtils.java, line 190)
+03.09.2009 17:21:13 *INFO * [http-8080-1] WebServiceLoader: New singleton WebService '/TicketOrderService/TicketOrderServicePort' registered. (WebServiceLoader.java, line 95)
+03.09.2009 17:21:27 *INFO * [http-8080-1] TicketOrderServiceImpl: Ticket {, , , null, 1251991287079} (TicketOrderServiceImpl.java, line 57)
+03.09.2009 17:21:27 *INFO * [http-8080-1] TicketOrderServiceImpl: Confirmation : false for order '1251991287079'. (TicketOrderServiceImpl.java, line 65)</programlisting>
+
+ <para>Now, your service is started and you can retrieve the WSDL at :
+ <link
+ linkend="???">http://localhost:8080/ws-examples/soap/services/TicketOrderService/Ticket...</link></para>
+ </section>
+</chapter>
Modified: jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
===================================================================
--- jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-05-28 09:56:00 UTC (rev 2441)
+++ jcr/trunk/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-05-28 09:59:52 UTC (rev 2442)
@@ -8,4 +8,53 @@
<xi:include href="ws/ws.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/introduction-to-rest.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-service-tutorial.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-migration-to-jsr311.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/groovy-scripts-as-rest-services.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/rest-framework.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/soap-service-tutorial.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/central-authentication-service-configuration.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/kerberos-sso-on-active-directory.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/oauth.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd-cluster.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/framework-for-cross-domain-ajax.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/cometd-cluster-bench.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/javascript-webdav-library.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/exo-ws-2-0.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="ws/exo-ws-2-0-1.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
</part>
Added: jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/ajax-how-it-works.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/ajax.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-bench.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/cometd-cluster.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console1.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console2.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/groovy-console3.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/javascript-webdav.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/oauth-scheme.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/rest-build-process.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/rest-run-process.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme-detailed.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
===================================================================
(Binary files differ)
Property changes on: jcr/trunk/docs/reference/en/src/main/resources/images/rest-scheme.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
13 years, 11 months
exo-jcr SVN: r2441 - jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2010-05-28 05:56:00 -0400 (Fri, 28 May 2010)
New Revision: 2441
Modified:
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
Log:
EXOJCR-744 : upgrading to Lucene 2.9:
Weight.score(IndexReader, boolean, boolean) usage changed a bit.
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java 2010-05-28 06:54:18 UTC (rev 2440)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java 2010-05-28 09:56:00 UTC (rev 2441)
@@ -103,7 +103,7 @@
}
if (hits == null) {
if (sort == null) {
- hits = new LuceneQueryHits(reader, this, query, true, false);
+ hits = new LuceneQueryHits(reader, this, query);
} else {
hits = new SortedLuceneQueryHits(
reader, this, query, sort, resultFetchHint);
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java 2010-05-28 06:54:18 UTC (rev 2440)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java 2010-05-28 09:56:00 UTC (rev 2441)
@@ -41,10 +41,10 @@
*/
private final Scorer scorer;
- public LuceneQueryHits(IndexReader reader, IndexSearcher searcher, Query query, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ public LuceneQueryHits(IndexReader reader, IndexSearcher searcher, Query query) throws IOException
{
this.reader = reader;
- this.scorer = query.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ this.scorer = query.weight(searcher).scorer(reader, true, false);
}
/**
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2010-05-28 06:54:18 UTC (rev 2440)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2010-05-28 09:56:00 UTC (rev 2441)
@@ -2745,7 +2745,7 @@
IndexSearcher searcher = new IndexSearcher(reader);
searcher.setSimilarity(getSimilarity());
- return new LuceneQueryHits(reader, searcher, query, true, false);
+ return new LuceneQueryHits(reader, searcher, query);
}
/**
13 years, 11 months
exo-jcr SVN: r2440 - in jcr/branches/1.12-LIC-709/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/core/query/lucene/directory and 1 other directories.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2010-05-28 02:54:18 -0400 (Fri, 28 May 2010)
New Revision: 2440
Modified:
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/AbstractWeight.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ChildAxisQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DerefQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DescendantSelfAxisQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrTermQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllWeight.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NotQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ParentAxisQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/QueryHitsQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RangeQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RefCountingIndexReader.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SingleIndex.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/WildcardQuery.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/directory/FSDirectoryManager.java
jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java
Log:
EXOJCR-744 : upgrading to Lucene 2.9:
1. Query class: changed definition (visibility modifier) of createWeight(..) method.
2. Interface Weight replaced with it's abstract type.
3. Weight.score(IndexReader) replaced with Weight.score(IndexReader, boolean, boolean) [should be reviewed if upgrading to 2.9 on trunk].
4. IndexReader.getSequenceReaders() introduced and used in LucenInternals for per-segment search and caching. In our custom IndexReader should be overridden and return null (This is safe solution confirmed within lucene's mailing list by Simon Willnauer).
5. FSdirectory.getDirectory(...) replaced with FSdirectory.open(...). But open(...) doesn't create a directory structure anymore.
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/AbstractWeight.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/AbstractWeight.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/AbstractWeight.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,72 +16,81 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Weight;
+import java.io.IOException;
+
/**
* <code>AbstractWeight</code> implements base functionality for custom lucene
* weights in jackrabbit.
*/
-abstract class AbstractWeight implements Weight {
+abstract class AbstractWeight extends Weight
+{
- /**
- * The searcher for this weight.
- */
- protected final Searcher searcher;
+ /**
+ * The searcher for this weight.
+ */
+ protected final Searcher searcher;
- /**
- * Creates a new <code>AbstractWeight</code> for the given
- * <code>searcher</code>.
- *
- * @param searcher the searcher instance for this weight.
- */
- public AbstractWeight(Searcher searcher) {
- this.searcher = searcher;
- }
+ /**
+ * Creates a new <code>AbstractWeight</code> for the given
+ * <code>searcher</code>.
+ *
+ * @param searcher the searcher instance for this weight.
+ */
+ public AbstractWeight(Searcher searcher)
+ {
+ this.searcher = searcher;
+ }
- /**
- * Abstract factory method for crating a scorer instance for the
- * specified reader.
- *
- * @param reader the index reader the created scorer instance should use
- * @return the scorer instance
- * @throws IOException if an error occurs while reading from the index
- */
- protected abstract Scorer createScorer(IndexReader reader)
- throws IOException;
+ /**
+ * Abstract factory method for crating a scorer instance for the
+ * specified reader.
+ *
+ * @param reader the index reader the created scorer instance should use
+ * @return the scorer instance
+ * @throws IOException if an error occurs while reading from the index
+ */
+ protected abstract Scorer createScorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer)
+ throws IOException;
- /**
- * {@inheritDoc}
- * <p/>
- * Returns a {@link MultiScorer} if the passed <code>reader</code> is of
- * type {@link MultiIndexReader}.
- */
- public Scorer scorer(IndexReader reader) throws IOException {
- if (reader instanceof MultiIndexReader) {
- MultiIndexReader mir = (MultiIndexReader) reader;
- IndexReader[] readers = mir.getIndexReaders();
- int[] starts = new int[readers.length + 1];
- int maxDoc = 0;
- for (int i = 0; i < readers.length; i++) {
- starts[i] = maxDoc;
- maxDoc += readers[i].maxDoc();
- }
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Returns a {@link MultiScorer} if the passed <code>reader</code> is of
+ * type {@link MultiIndexReader}.
+ */
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ if (reader instanceof MultiIndexReader)
+ {
+ MultiIndexReader mir = (MultiIndexReader)reader;
+ IndexReader[] readers = mir.getIndexReaders();
+ int[] starts = new int[readers.length + 1];
+ int maxDoc = 0;
+ for (int i = 0; i < readers.length; i++)
+ {
+ starts[i] = maxDoc;
+ maxDoc += readers[i].maxDoc();
+ }
- starts[readers.length] = maxDoc;
- Scorer[] scorers = new Scorer[readers.length];
- for (int i = 0; i < readers.length; i++) {
- scorers[i] = scorer(readers[i]);
- }
+ starts[readers.length] = maxDoc;
+ Scorer[] scorers = new Scorer[readers.length];
+ for (int i = 0; i < readers.length; i++)
+ {
+ scorers[i] = scorer(readers[i], scoreDocsInOrder, topScorer);
+ }
- return new MultiScorer(searcher.getSimilarity(), scorers, starts);
- } else {
- return createScorer(reader);
- }
- }
+ return new MultiScorer(searcher.getSimilarity(), scorers, starts);
+ }
+ else
+ {
+ return createScorer(reader, scoreDocsInOrder, topScorer);
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ChildAxisQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ChildAxisQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ChildAxisQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -192,7 +192,8 @@
* @param searcher the <code>Searcher</code> instance to use.
* @return a <code>ChildAxisWeight</code>.
*/
- protected Weight createWeight(Searcher searcher)
+ @Override
+ public Weight createWeight(Searcher searcher)
{
return new ChildAxisWeight(searcher);
}
@@ -200,6 +201,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void extractTerms(Set terms)
{
contextQuery.extractTerms(terms);
@@ -208,6 +210,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Query rewrite(IndexReader reader) throws IOException
{
Query cQuery = contextQuery.rewrite(reader);
@@ -247,6 +250,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public String toString(String field)
{
StringBuffer sb = new StringBuffer();
@@ -286,7 +290,7 @@
/**
* The <code>Weight</code> implementation for this <code>ChildAxisQuery</code>.
*/
- private class ChildAxisWeight implements Weight
+ private class ChildAxisWeight extends Weight
{
/**
@@ -310,6 +314,7 @@
*
* @return this <code>ChildAxisQuery</code>.
*/
+ @Override
public Query getQuery()
{
return ChildAxisQuery.this;
@@ -318,6 +323,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float getValue()
{
return 1.0f;
@@ -326,6 +332,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float sumOfSquaredWeights() throws IOException
{
return 1.0f;
@@ -334,6 +341,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void normalize(float norm)
{
}
@@ -345,12 +353,15 @@
* @return a <code>ChildAxisScorer</code>.
* @throws IOException if an error occurs while reading from the index.
*/
- public Scorer scorer(IndexReader reader) throws IOException
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
{
- contextScorer = contextQuery.weight(searcher).scorer(reader);
+ contextScorer = contextQuery.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
if (nameTest != null)
{
- nameTestScorer = new NameQuery(nameTest, version, nsMappings).weight(searcher).scorer(reader);
+ nameTestScorer =
+ new NameQuery(nameTest, version, nsMappings).weight(searcher)
+ .scorer(reader, scoreDocsInOrder, topScorer);
}
return new ChildAxisScorer(searcher.getSimilarity(), reader, (HierarchyResolver)reader);
}
@@ -358,6 +369,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Explanation explain(IndexReader reader, int doc) throws IOException
{
return new Explanation();
@@ -409,6 +421,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean next() throws IOException
{
calculateChildren();
@@ -424,6 +437,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public int doc()
{
return nextDoc;
@@ -432,6 +446,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float score() throws IOException
{
return 1.0f;
@@ -440,6 +455,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean skipTo(int target) throws IOException
{
calculateChildren();
@@ -457,6 +473,7 @@
* @throws UnsupportedOperationException this implementation always
* throws an <code>UnsupportedOperationException</code>.
*/
+ @Override
public Explanation explain(int doc) throws IOException
{
throw new UnsupportedOperationException();
@@ -474,6 +491,7 @@
calc[0] = new SimpleChildrenCalculator(reader, hResolver);
contextScorer.score(new HitCollector()
{
+ @Override
public void collect(int doc, float score)
{
calc[0].collectContextHit(doc);
@@ -489,6 +507,7 @@
private List docIds = new ArrayList();
+ @Override
public void collect(int doc, float score)
{
calc[0].collectContextHit(doc);
@@ -583,7 +602,9 @@
else
{
if (nodeData.getQPath().getIndex() != position)
+ {
return false;
+ }
}
}
}
@@ -667,6 +688,7 @@
/**
* {@inheritDoc}
*/
+ @Override
protected void collectContextHit(int doc)
{
contextHits.set(doc);
@@ -675,6 +697,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Hits getHits() throws IOException
{
// read the uuids of the context nodes
@@ -709,7 +732,9 @@
for (NodeData nodeData : childs)
{
if (nameTest.equals(nodeData.getQPath().getName()))
+ {
datas.add(nodeData);
+ }
}
}
@@ -775,6 +800,7 @@
/**
* {@inheritDoc}
*/
+ @Override
protected void collectContextHit(int doc)
{
docIds.add(new Integer(doc));
@@ -783,6 +809,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Hits getHits() throws IOException
{
long time = System.currentTimeMillis();
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DerefQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DerefQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DerefQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,13 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
@@ -35,315 +28,383 @@
import org.apache.lucene.search.Weight;
import org.exoplatform.services.jcr.datamodel.InternalQName;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
/**
* Implements a lucene <code>Query</code> which returns the nodes selected by
* a reference property of the context node.
*/
-class DerefQuery extends Query {
+class DerefQuery extends Query
+{
- /**
- * The context query
- */
- private final Query contextQuery;
+ /**
+ * The context query
+ */
+ private final Query contextQuery;
- /**
- * The name of the reference property.
- */
- private final String refProperty;
+ /**
+ * The name of the reference property.
+ */
+ private final String refProperty;
- /**
- * The nameTest to apply on target node, or <code>null</code> if all
- * target nodes should be selected.
- */
- private final InternalQName nameTest;
+ /**
+ * The nameTest to apply on target node, or <code>null</code> if all
+ * target nodes should be selected.
+ */
+ private final InternalQName nameTest;
- /**
- * The index format version.
- */
- private final IndexFormatVersion version;
+ /**
+ * The index format version.
+ */
+ private final IndexFormatVersion version;
- /**
- * The internal namespace mappings.
- */
- private final NamespaceMappings nsMappings;
+ /**
+ * The internal namespace mappings.
+ */
+ private final NamespaceMappings nsMappings;
- /**
- * The scorer of the context query
- */
- private Scorer contextScorer;
+ /**
+ * The scorer of the context query
+ */
+ private Scorer contextScorer;
- /**
- * The scorer of the name test query
- */
- private Scorer nameTestScorer;
+ /**
+ * The scorer of the name test query
+ */
+ private Scorer nameTestScorer;
- /**
- * Creates a new <code>DerefQuery</code> based on a <code>context</code>
- * query.
- *
- * @param context the context for this query.
- * @param refProperty the name of the reference property.
- * @param nameTest a name test or <code>null</code> if any node is
- * selected.
- * @param version the index format version.
- * @param nsMappings the namespace mappings.
- */
- DerefQuery(Query context, String refProperty, InternalQName nameTest,
- IndexFormatVersion version, NamespaceMappings nsMappings) {
- this.contextQuery = context;
- this.refProperty = refProperty;
- this.nameTest = nameTest;
- this.version = version;
- this.nsMappings = nsMappings;
- }
+ /**
+ * Creates a new <code>DerefQuery</code> based on a <code>context</code>
+ * query.
+ *
+ * @param context the context for this query.
+ * @param refProperty the name of the reference property.
+ * @param nameTest a name test or <code>null</code> if any node is
+ * selected.
+ * @param version the index format version.
+ * @param nsMappings the namespace mappings.
+ */
+ DerefQuery(Query context, String refProperty, InternalQName nameTest, IndexFormatVersion version,
+ NamespaceMappings nsMappings)
+ {
+ this.contextQuery = context;
+ this.refProperty = refProperty;
+ this.nameTest = nameTest;
+ this.version = version;
+ this.nsMappings = nsMappings;
+ }
- /**
- * Creates a <code>Weight</code> instance for this query.
- *
- * @param searcher the <code>Searcher</code> instance to use.
- * @return a <code>DerefWeight</code>.
- */
- protected Weight createWeight(Searcher searcher) {
- return new DerefWeight(searcher);
- }
+ /**
+ * Creates a <code>Weight</code> instance for this query.
+ *
+ * @param searcher the <code>Searcher</code> instance to use.
+ * @return a <code>DerefWeight</code>.
+ */
+ @Override
+ public Weight createWeight(Searcher searcher)
+ {
+ return new DerefWeight(searcher);
+ }
- /**
- * Always returns 'DerefQuery'.
- *
- * @param field the name of a field.
- * @return 'DerefQuery'.
- */
- public String toString(String field) {
- return "DerefQuery";
- }
+ /**
+ * Always returns 'DerefQuery'.
+ *
+ * @param field the name of a field.
+ * @return 'DerefQuery'.
+ */
+ @Override
+ public String toString(String field)
+ {
+ return "DerefQuery";
+ }
- /**
- * {@inheritDoc}
- */
- public void extractTerms(Set terms) {
- // no terms to extract
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void extractTerms(Set terms)
+ {
+ // no terms to extract
+ }
- /**
- * {@inheritDoc}
- */
- public Query rewrite(IndexReader reader) throws IOException {
- Query cQuery = contextQuery.rewrite(reader);
- if (cQuery == contextQuery) {
- return this;
- } else {
- return new DerefQuery(cQuery, refProperty, nameTest, version, nsMappings);
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Query rewrite(IndexReader reader) throws IOException
+ {
+ Query cQuery = contextQuery.rewrite(reader);
+ if (cQuery == contextQuery)
+ {
+ return this;
+ }
+ else
+ {
+ return new DerefQuery(cQuery, refProperty, nameTest, version, nsMappings);
+ }
+ }
- //-------------------< DerefWeight >------------------------------------
+ //-------------------< DerefWeight >------------------------------------
- /**
- * The <code>Weight</code> implementation for this <code>DerefQuery</code>.
- */
- private class DerefWeight implements Weight {
+ /**
+ * The <code>Weight</code> implementation for this <code>DerefQuery</code>.
+ */
+ private class DerefWeight extends Weight
+ {
- /**
- * The searcher in use
- */
- private final Searcher searcher;
+ /**
+ * The searcher in use
+ */
+ private final Searcher searcher;
- /**
- * Creates a new <code>DerefWeight</code> instance using
- * <code>searcher</code>.
- *
- * @param searcher a <code>Searcher</code> instance.
- */
- private DerefWeight(Searcher searcher) {
- this.searcher = searcher;
- }
+ /**
+ * Creates a new <code>DerefWeight</code> instance using
+ * <code>searcher</code>.
+ *
+ * @param searcher a <code>Searcher</code> instance.
+ */
+ private DerefWeight(Searcher searcher)
+ {
+ this.searcher = searcher;
+ }
- /**
- * Returns this <code>DerefQuery</code>.
- *
- * @return this <code>DerefQuery</code>.
- */
- public Query getQuery() {
- return DerefQuery.this;
- }
+ /**
+ * Returns this <code>DerefQuery</code>.
+ *
+ * @return this <code>DerefQuery</code>.
+ */
+ @Override
+ public Query getQuery()
+ {
+ return DerefQuery.this;
+ }
- /**
- * {@inheritDoc}
- */
- public float getValue() {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getValue()
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public float sumOfSquaredWeights() throws IOException {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float sumOfSquaredWeights() throws IOException
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public void normalize(float norm) {
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void normalize(float norm)
+ {
+ }
- /**
- * Creates a scorer for this <code>DerefQuery</code>.
- *
- * @param reader a reader for accessing the index.
- * @return a <code>DerefScorer</code>.
- * @throws IOException if an error occurs while reading from the index.
- */
- public Scorer scorer(IndexReader reader) throws IOException {
- contextScorer = contextQuery.weight(searcher).scorer(reader);
- if (nameTest != null) {
- nameTestScorer = new NameQuery(nameTest, version, nsMappings).weight(searcher).scorer(reader);
- }
- return new DerefScorer(searcher.getSimilarity(), reader);
- }
+ /**
+ * Creates a scorer for this <code>DerefQuery</code>.
+ *
+ * @param reader a reader for accessing the index.
+ * @return a <code>DerefScorer</code>.
+ * @throws IOException if an error occurs while reading from the index.
+ */
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ contextScorer = contextQuery.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ if (nameTest != null)
+ {
+ nameTestScorer =
+ new NameQuery(nameTest, version, nsMappings).weight(searcher)
+ .scorer(reader, scoreDocsInOrder, topScorer);
+ }
+ return new DerefScorer(searcher.getSimilarity(), reader);
+ }
- /**
- * {@inheritDoc}
- */
- public Explanation explain(IndexReader reader, int doc) throws IOException {
- return new Explanation();
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException
+ {
+ return new Explanation();
+ }
+ }
- //----------------------< DerefScorer >---------------------------------
+ //----------------------< DerefScorer >---------------------------------
- /**
- * Implements a <code>Scorer</code> for this <code>DerefQuery</code>.
- */
- private class DerefScorer extends Scorer {
+ /**
+ * Implements a <code>Scorer</code> for this <code>DerefQuery</code>.
+ */
+ private class DerefScorer extends Scorer
+ {
- /**
- * An <code>IndexReader</code> to access the index.
- */
- private final IndexReader reader;
+ /**
+ * An <code>IndexReader</code> to access the index.
+ */
+ private final IndexReader reader;
- /**
- * BitSet storing the id's of selected documents
- */
- private final BitSet hits;
+ /**
+ * BitSet storing the id's of selected documents
+ */
+ private final BitSet hits;
- /**
- * List of UUIDs of selected nodes
- */
- private List uuids = null;
+ /**
+ * List of UUIDs of selected nodes
+ */
+ private List uuids = null;
- /**
- * The next document id to return
- */
- private int nextDoc = -1;
+ /**
+ * The next document id to return
+ */
+ private int nextDoc = -1;
- /**
- * Creates a new <code>DerefScorer</code>.
- *
- * @param similarity the <code>Similarity</code> instance to use.
- * @param reader for index access.
- */
- protected DerefScorer(Similarity similarity, IndexReader reader) {
- super(similarity);
- this.reader = reader;
- this.hits = new BitSet(reader.maxDoc());
- }
+ /**
+ * Creates a new <code>DerefScorer</code>.
+ *
+ * @param similarity the <code>Similarity</code> instance to use.
+ * @param reader for index access.
+ */
+ protected DerefScorer(Similarity similarity, IndexReader reader)
+ {
+ super(similarity);
+ this.reader = reader;
+ this.hits = new BitSet(reader.maxDoc());
+ }
- /**
- * {@inheritDoc}
- */
- public boolean next() throws IOException {
- calculateChildren();
- nextDoc = hits.nextSetBit(nextDoc + 1);
- return nextDoc > -1;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean next() throws IOException
+ {
+ calculateChildren();
+ nextDoc = hits.nextSetBit(nextDoc + 1);
+ return nextDoc > -1;
+ }
- /**
- * {@inheritDoc}
- */
- public int doc() {
- return nextDoc;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int doc()
+ {
+ return nextDoc;
+ }
- /**
- * {@inheritDoc}
- */
- public float score() throws IOException {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float score() throws IOException
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public boolean skipTo(int target) throws IOException {
- calculateChildren();
- nextDoc = hits.nextSetBit(target);
- return nextDoc > -1;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean skipTo(int target) throws IOException
+ {
+ calculateChildren();
+ nextDoc = hits.nextSetBit(target);
+ return nextDoc > -1;
+ }
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException this implementation always
- * throws an <code>UnsupportedOperationException</code>.
- */
- public Explanation explain(int doc) throws IOException {
- throw new UnsupportedOperationException();
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException this implementation always
+ * throws an <code>UnsupportedOperationException</code>.
+ */
+ @Override
+ public Explanation explain(int doc) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
- private void calculateChildren() throws IOException {
- if (uuids == null) {
- uuids = new ArrayList();
- contextScorer.score(new HitCollector() {
- public void collect(int doc, float score) {
- hits.set(doc);
- }
- });
+ private void calculateChildren() throws IOException
+ {
+ if (uuids == null)
+ {
+ uuids = new ArrayList();
+ contextScorer.score(new HitCollector()
+ {
+ @Override
+ public void collect(int doc, float score)
+ {
+ hits.set(doc);
+ }
+ });
- // collect nameTest hits
- final BitSet nameTestHits = new BitSet();
- if (nameTestScorer != null) {
- nameTestScorer.score(new HitCollector() {
- public void collect(int doc, float score) {
- nameTestHits.set(doc);
- }
- });
- }
+ // collect nameTest hits
+ final BitSet nameTestHits = new BitSet();
+ if (nameTestScorer != null)
+ {
+ nameTestScorer.score(new HitCollector()
+ {
+ @Override
+ public void collect(int doc, float score)
+ {
+ nameTestHits.set(doc);
+ }
+ });
+ }
- // retrieve uuids of target nodes
- String prefix = FieldNames.createNamedValue(refProperty, "");
- for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
- String[] values = reader.document(i).getValues(FieldNames.PROPERTIES);
- if (values == null) {
- // no reference properties at all on this node
- continue;
- }
- for (int v = 0; v < values.length; v++) {
- if (values[v].startsWith(prefix)) {
- uuids.add(values[v].substring(prefix.length()));
- }
- }
- }
+ // retrieve uuids of target nodes
+ String prefix = FieldNames.createNamedValue(refProperty, "");
+ for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1))
+ {
+ String[] values = reader.document(i).getValues(FieldNames.PROPERTIES);
+ if (values == null)
+ {
+ // no reference properties at all on this node
+ continue;
+ }
+ for (int v = 0; v < values.length; v++)
+ {
+ if (values[v].startsWith(prefix))
+ {
+ uuids.add(values[v].substring(prefix.length()));
+ }
+ }
+ }
- // collect the doc ids of all target nodes. we reuse the existing
- // bitset.
- hits.clear();
- for (Iterator it = uuids.iterator(); it.hasNext();) {
- TermDocs node = reader.termDocs(new Term(FieldNames.UUID, (String) it.next()));
- try {
- while (node.next()) {
- hits.set(node.doc());
- }
- } finally {
- node.close();
- }
- }
- // filter out the target nodes that do not match the name test
- // if there is any name test at all.
- if (nameTestScorer != null) {
- hits.and(nameTestHits);
- }
+ // collect the doc ids of all target nodes. we reuse the existing
+ // bitset.
+ hits.clear();
+ for (Iterator it = uuids.iterator(); it.hasNext();)
+ {
+ TermDocs node = reader.termDocs(new Term(FieldNames.UUID, (String)it.next()));
+ try
+ {
+ while (node.next())
+ {
+ hits.set(node.doc());
+ }
+ }
+ finally
+ {
+ node.close();
+ }
}
- }
- }
+ // filter out the target nodes that do not match the name test
+ // if there is any name test at all.
+ if (nameTestScorer != null)
+ {
+ hits.and(nameTestHits);
+ }
+ }
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DescendantSelfAxisQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DescendantSelfAxisQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/DescendantSelfAxisQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -181,7 +181,8 @@
* @param searcher the <code>Searcher</code> instance to use.
* @return a <code>DescendantSelfAxisWeight</code>.
*/
- protected Weight createWeight(Searcher searcher)
+ @Override
+ public Weight createWeight(Searcher searcher)
{
return new DescendantSelfAxisWeight(searcher);
}
@@ -189,6 +190,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public String toString(String field)
{
StringBuffer sb = new StringBuffer();
@@ -205,6 +207,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void extractTerms(Set terms)
{
contextQuery.extractTerms(terms);
@@ -214,6 +217,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Query rewrite(IndexReader reader) throws IOException
{
Query cQuery = contextQuery.rewrite(reader);
@@ -314,6 +318,7 @@
fetchNextTraversal();
}
+ @Override
public void close() throws IOException
{
if (currentTraversal != null)
@@ -379,7 +384,7 @@
* The <code>Weight</code> implementation for this
* <code>DescendantSelfAxisWeight</code>.
*/
- private class DescendantSelfAxisWeight implements Weight
+ private class DescendantSelfAxisWeight extends Weight
{
/**
@@ -405,6 +410,7 @@
*
* @return this <code>DescendantSelfAxisQuery</code>.
*/
+ @Override
public Query getQuery()
{
return DescendantSelfAxisQuery.this;
@@ -413,6 +419,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float getValue()
{
return 1.0f;
@@ -421,6 +428,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float sumOfSquaredWeights() throws IOException
{
return 1.0f;
@@ -429,6 +437,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void normalize(float norm)
{
}
@@ -440,10 +449,11 @@
* @return a <code>DescendantSelfAxisScorer</code>.
* @throws IOException if an error occurs while reading from the index.
*/
- public Scorer scorer(IndexReader reader) throws IOException
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
{
- contextScorer = contextQuery.weight(searcher).scorer(reader);
- subScorer = subQuery.weight(searcher).scorer(reader);
+ contextScorer = contextQuery.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ subScorer = subQuery.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
HierarchyResolver resolver = (HierarchyResolver)reader;
return new DescendantSelfAxisScorer(searcher.getSimilarity(), reader, resolver);
}
@@ -451,6 +461,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Explanation explain(IndexReader reader, int doc) throws IOException
{
return new Explanation();
@@ -513,6 +524,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean next() throws IOException
{
collectContextHits();
@@ -538,6 +550,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public int doc()
{
return subScorer.doc();
@@ -546,6 +559,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float score() throws IOException
{
return subScorer.score();
@@ -554,6 +568,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean skipTo(int target) throws IOException
{
boolean match = subScorer.skipTo(target);
@@ -575,6 +590,7 @@
long time = System.currentTimeMillis();
contextScorer.score(new HitCollector()
{
+ @Override
public void collect(int doc, float score)
{
contextHits.set(doc);
@@ -594,6 +610,7 @@
* @throws UnsupportedOperationException this implementation always
* throws an <code>UnsupportedOperationException</code>.
*/
+ @Override
public Explanation explain(int doc) throws IOException
{
throw new UnsupportedOperationException();
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrIndexSearcher.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,8 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -27,6 +25,8 @@
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.impl.core.query.lucene.constraint.EvaluationContext;
+import java.io.IOException;
+
/**
* <code>JackrabbitIndexSearcher</code> implements an index searcher with
* jackrabbit specific optimizations.
@@ -103,7 +103,7 @@
}
if (hits == null) {
if (sort == null) {
- hits = new LuceneQueryHits(reader, this, query);
+ hits = new LuceneQueryHits(reader, this, query, true, false);
} else {
hits = new SortedLuceneQueryHits(
reader, this, query, sort, resultFetchHint);
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrTermQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrTermQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/JcrTermQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,8 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Explanation;
@@ -27,80 +25,99 @@
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Weight;
+import java.io.IOException;
+
/**
* <code>JackrabbitTermQuery</code> implements a {@link TermQuery} where score
* values are retrieved on a per index segment basis using {@link MultiScorer}.
*/
-public class JcrTermQuery extends TermQuery {
+public class JcrTermQuery extends TermQuery
+{
- private static final long serialVersionUID = 4244799812287335957L;
+ private static final long serialVersionUID = 4244799812287335957L;
- public JcrTermQuery(Term t) {
- super(t);
- }
+ public JcrTermQuery(Term t)
+ {
+ super(t);
+ }
- protected Weight createWeight(Searcher searcher) throws IOException {
- return new JackrabbitTermWeight(searcher, super.createWeight(searcher));
- }
+ @Override
+ public Weight createWeight(Searcher searcher) throws IOException
+ {
+ return new JackrabbitTermWeight(searcher, super.createWeight(searcher));
+ }
- /**
- * The weight implementation.
- */
- protected class JackrabbitTermWeight extends AbstractWeight {
+ /**
+ * The weight implementation.
+ */
+ protected class JackrabbitTermWeight extends AbstractWeight
+ {
- private static final long serialVersionUID = -2070964510010945854L;
+ private static final long serialVersionUID = -2070964510010945854L;
- /**
- * The default lucene TermQuery weight.
- */
- private final Weight weight;
+ /**
+ * The default lucene TermQuery weight.
+ */
+ private final Weight weight;
- public JackrabbitTermWeight(Searcher searcher, Weight weight) {
- super(searcher);
- this.weight = weight;
- }
+ public JackrabbitTermWeight(Searcher searcher, Weight weight)
+ {
+ super(searcher);
+ this.weight = weight;
+ }
- /**
- * {@inheritDoc}
- */
- protected Scorer createScorer(IndexReader reader) throws IOException {
- return weight.scorer(reader);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Scorer createScorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ return weight.scorer(reader, scoreDocsInOrder, topScorer);
+ }
- /**
- * {@inheritDoc}
- */
- public Query getQuery() {
- return JcrTermQuery.this;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Query getQuery()
+ {
+ return JcrTermQuery.this;
+ }
- /**
- * {@inheritDoc}
- */
- public float getValue() {
- return weight.getValue();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getValue()
+ {
+ return weight.getValue();
+ }
- /**
- * {@inheritDoc}
- */
- public float sumOfSquaredWeights() throws IOException {
- return weight.sumOfSquaredWeights();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float sumOfSquaredWeights() throws IOException
+ {
+ return weight.sumOfSquaredWeights();
+ }
- /**
- * {@inheritDoc}
- */
- public void normalize(float norm) {
- weight.normalize(norm);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void normalize(float norm)
+ {
+ weight.normalize(norm);
+ }
- /**
- * {@inheritDoc}
- */
- public Explanation explain(IndexReader reader, int doc) throws
- IOException {
- return weight.explain(reader, doc);
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException
+ {
+ return weight.explain(reader, doc);
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/LuceneQueryHits.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -23,67 +23,72 @@
import java.io.IOException;
-
/**
* Wraps a lucene query result and adds a close method that allows to release
* resources after a query has been executed and the results have been read
* completely.
*/
-public class LuceneQueryHits implements QueryHits {
+public class LuceneQueryHits implements QueryHits
+{
- /**
- * The IndexReader in use by the lucene hits.
- */
- private final IndexReader reader;
+ /**
+ * The IndexReader in use by the lucene hits.
+ */
+ private final IndexReader reader;
- /**
- * The scorer for the query.
- */
- private final Scorer scorer;
+ /**
+ * The scorer for the query.
+ */
+ private final Scorer scorer;
- public LuceneQueryHits(IndexReader reader,
- IndexSearcher searcher,
- Query query)
- throws IOException {
- this.reader = reader;
- this.scorer = query.weight(searcher).scorer(reader);
- }
+ public LuceneQueryHits(IndexReader reader, IndexSearcher searcher, Query query, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ this.reader = reader;
+ this.scorer = query.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ }
- /**
- * {@inheritDoc}
- */
- public ScoreNode nextScoreNode() throws IOException {
- if (!scorer.next()) {
- return null;
- }
- int doc = scorer.doc();
- String uuid = reader.document(doc).get(FieldNames.UUID);
- return new ScoreNode(uuid, scorer.score(), doc);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public ScoreNode nextScoreNode() throws IOException
+ {
+ if (!scorer.next())
+ {
+ return null;
+ }
+ int doc = scorer.doc();
+ String uuid = reader.document(doc).get(FieldNames.UUID);
+ return new ScoreNode(uuid, scorer.score(), doc);
+ }
- /**
- * {@inheritDoc}
- */
- public void close() throws IOException {
- // make sure scorer frees resources
- scorer.skipTo(Integer.MAX_VALUE);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws IOException
+ {
+ // make sure scorer frees resources
+ scorer.skipTo(Integer.MAX_VALUE);
+ }
- /**
- * @return always -1.
- */
- public int getSize() {
- return -1;
- }
+ /**
+ * @return always -1.
+ */
+ public int getSize()
+ {
+ return -1;
+ }
- /**
- * {@inheritDoc}
- */
- public void skip(int n) throws IOException {
- while (n-- > 0) {
- if (nextScoreNode() == null) {
- return;
- }
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public void skip(int n) throws IOException
+ {
+ while (n-- > 0)
+ {
+ if (nextScoreNode() == null)
+ {
+ return;
+ }
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,12 +16,12 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.util.Set;
-
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Weight;
+import java.util.Set;
+
/**
* Specialized query that returns / scores all pages in the search index.
* <p>Use this Query to perform a match '*'.
@@ -50,7 +50,8 @@
* @param searcher the current searcher.
* @return the <code>Weight</code> for this Query.
*/
- protected Weight createWeight(Searcher searcher) {
+ @Override
+ public Weight createWeight(Searcher searcher) {
return new MatchAllWeight(this, searcher, field);
}
@@ -60,13 +61,15 @@
* @param field default field for the query.
* @return the String "%".
*/
- public String toString(String field) {
+ @Override
+ public String toString(String field) {
return "%";
}
/**
* Does nothing but simply returns. There are no terms to extract.
*/
- public void extractTerms(Set terms) {
+ @Override
+ public void extractTerms(Set terms) {
}
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllWeight.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllWeight.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MatchAllWeight.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,8 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
@@ -25,6 +23,8 @@
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Similarity;
+import java.io.IOException;
+
/**
* This class implements the Weight calculation for the MatchAllQuery.
*/
@@ -72,28 +72,32 @@
* @param reader index reader
* @return a {@link MatchAllScorer} instance
*/
- protected Scorer createScorer(IndexReader reader) throws IOException {
+ @Override
+ protected Scorer createScorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException {
return new MatchAllScorer(reader, field);
}
/**
* {@inheritDoc}
*/
- public Query getQuery() {
+ @Override
+ public Query getQuery() {
return query;
}
/**
* {@inheritDoc}
*/
- public float getValue() {
+ @Override
+ public float getValue() {
return value;
}
/**
* {@inheritDoc}
*/
- public float sumOfSquaredWeights() throws IOException {
+ @Override
+ public float sumOfSquaredWeights() throws IOException {
idf = searcher.getSimilarity().idf(searcher.maxDoc(), searcher.maxDoc()); // compute idf
queryWeight = idf * 1.0f; // boost // compute query weight
return queryWeight * queryWeight; // square it
@@ -102,7 +106,8 @@
/**
* {@inheritDoc}
*/
- public void normalize(float queryNorm) {
+ @Override
+ public void normalize(float queryNorm) {
queryWeight *= queryNorm; // normalize query weight
value = queryWeight * idf; // idf for document
}
@@ -110,7 +115,8 @@
/**
* {@inheritDoc}
*/
- public Explanation explain(IndexReader reader, int doc) throws IOException {
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException {
return new Explanation(Similarity.getDefault().idf(reader.maxDoc(), reader.maxDoc()),
"matchAll");
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NotQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NotQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NotQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,9 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-import java.util.Set;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
@@ -27,217 +24,271 @@
import org.apache.lucene.search.Similarity;
import org.apache.lucene.search.Weight;
+import java.io.IOException;
+import java.util.Set;
+
/**
* Implements a query that negates documents of a context query. Documents
* that matched the context query will not match the <code>NotQuery</code> and
* Documents that did not match the context query will be selected by this
* <code>NotQuery</code>.
*/
-class NotQuery extends Query {
+class NotQuery extends Query
+{
- /**
- * The context query to invert.
- */
- private final Query context;
+ /**
+ * The context query to invert.
+ */
+ private final Query context;
- /**
- * The context scorer to invert.
- */
- private Scorer contextScorer;
+ /**
+ * The context scorer to invert.
+ */
+ private Scorer contextScorer;
- /**
- * Creates a new <code>NotQuery</code>.
- * @param context the context query.
- */
- NotQuery(Query context) {
- this.context = context;
- }
+ /**
+ * Creates a new <code>NotQuery</code>.
+ * @param context the context query.
+ */
+ NotQuery(Query context)
+ {
+ this.context = context;
+ }
- /**
- * {@inheritDoc}
- */
- protected Weight createWeight(Searcher searcher) {
- return new NotQueryWeight(searcher);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Weight createWeight(Searcher searcher)
+ {
+ return new NotQueryWeight(searcher);
+ }
- /**
- * {@inheritDoc}
- */
- public String toString(String field) {
- return "NotQuery";
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString(String field)
+ {
+ return "NotQuery";
+ }
- /**
- * {@inheritDoc}
- */
- public void extractTerms(Set terms) {
- context.extractTerms(terms);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void extractTerms(Set terms)
+ {
+ context.extractTerms(terms);
+ }
- /**
- * {@inheritDoc}
- */
- public Query rewrite(IndexReader reader) throws IOException {
- Query cQuery = context.rewrite(reader);
- if (cQuery == context) {
- return this;
- } else {
- return new NotQuery(cQuery);
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Query rewrite(IndexReader reader) throws IOException
+ {
+ Query cQuery = context.rewrite(reader);
+ if (cQuery == context)
+ {
+ return this;
+ }
+ else
+ {
+ return new NotQuery(cQuery);
+ }
+ }
- /**
- * Implements a weight for this <code>NotQuery</code>.
- */
- private class NotQueryWeight implements Weight {
+ /**
+ * Implements a weight for this <code>NotQuery</code>.
+ */
+ private class NotQueryWeight extends Weight
+ {
- /**
- * The searcher to access the index.
- */
- private final Searcher searcher;
+ /**
+ * The searcher to access the index.
+ */
+ private final Searcher searcher;
- /**
- * Creates a new NotQueryWeight with a searcher.
- * @param searcher the searcher.
- */
- NotQueryWeight(Searcher searcher) {
- this.searcher = searcher;
- }
+ /**
+ * Creates a new NotQueryWeight with a searcher.
+ * @param searcher the searcher.
+ */
+ NotQueryWeight(Searcher searcher)
+ {
+ this.searcher = searcher;
+ }
- /**
- * @inheritDoc
- */
- public Query getQuery() {
- return NotQuery.this;
- }
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public Query getQuery()
+ {
+ return NotQuery.this;
+ }
- /**
- * @inheritDoc
- */
- public float getValue() {
- return 1.0f;
- }
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public float getValue()
+ {
+ return 1.0f;
+ }
- /**
- * @inheritDoc
- */
- public float sumOfSquaredWeights() throws IOException {
- return 1.0f;
- }
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public float sumOfSquaredWeights() throws IOException
+ {
+ return 1.0f;
+ }
- /**
- * @inheritDoc
- */
- public void normalize(float norm) {
- }
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public void normalize(float norm)
+ {
+ }
- /**
- * @inheritDoc
- */
- public Scorer scorer(IndexReader reader) throws IOException {
- contextScorer = context.weight(searcher).scorer(reader);
- return new NotQueryScorer(reader);
- }
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ contextScorer = context.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ return new NotQueryScorer(reader);
+ }
- /**
- * @throws UnsupportedOperationException always
- */
- public Explanation explain(IndexReader reader, int doc) throws IOException {
- throw new UnsupportedOperationException();
- }
- }
+ /**
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
- /**
- * Implements a scorer that inverts the document matches of the context
- * scorer.
- */
- private class NotQueryScorer extends Scorer {
+ /**
+ * Implements a scorer that inverts the document matches of the context
+ * scorer.
+ */
+ private class NotQueryScorer extends Scorer
+ {
- /**
- * The index reader.
- */
- private final IndexReader reader;
+ /**
+ * The index reader.
+ */
+ private final IndexReader reader;
- /**
- * Current document number.
- */
- private int docNo = -1;
+ /**
+ * Current document number.
+ */
+ private int docNo = -1;
- /**
- * Current document number of the context scorer;
- */
- private int contextNo = -1;
+ /**
+ * Current document number of the context scorer;
+ */
+ private int contextNo = -1;
- /**
- * Creates a new scorer
- * @param reader
- */
- NotQueryScorer(IndexReader reader) {
- super(Similarity.getDefault());
- this.reader = reader;
- }
+ /**
+ * Creates a new scorer
+ * @param reader
+ */
+ NotQueryScorer(IndexReader reader)
+ {
+ super(Similarity.getDefault());
+ this.reader = reader;
+ }
- /**
- * {@inheritDoc}
- */
- public boolean next() throws IOException {
- if (docNo == -1) {
- // get first doc of context scorer
- if (contextScorer.next()) {
- contextNo = contextScorer.doc();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean next() throws IOException
+ {
+ if (docNo == -1)
+ {
+ // get first doc of context scorer
+ if (contextScorer.next())
+ {
+ contextNo = contextScorer.doc();
}
- // move to next candidate
- do {
- docNo++;
- } while (reader.isDeleted(docNo) && docNo < reader.maxDoc());
+ }
+ // move to next candidate
+ do
+ {
+ docNo++;
+ }
+ while (reader.isDeleted(docNo) && docNo < reader.maxDoc());
- // check with contextScorer
- while (contextNo != -1 && contextNo == docNo) {
- docNo++;
- if (contextScorer.next()) {
- contextNo = contextScorer.doc();
- } else {
- contextNo = -1;
- }
+ // check with contextScorer
+ while (contextNo != -1 && contextNo == docNo)
+ {
+ docNo++;
+ if (contextScorer.next())
+ {
+ contextNo = contextScorer.doc();
}
- return docNo < reader.maxDoc();
- }
+ else
+ {
+ contextNo = -1;
+ }
+ }
+ return docNo < reader.maxDoc();
+ }
- /**
- * {@inheritDoc}
- */
- public int doc() {
- return docNo;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int doc()
+ {
+ return docNo;
+ }
- /**
- * {@inheritDoc}
- */
- public float score() throws IOException {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float score() throws IOException
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public boolean skipTo(int target) throws IOException {
- if (contextNo != -1 && contextNo < target) {
- if (contextScorer.skipTo(target)) {
- contextNo = contextScorer.doc();
- } else {
- contextNo = -1;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean skipTo(int target) throws IOException
+ {
+ if (contextNo != -1 && contextNo < target)
+ {
+ if (contextScorer.skipTo(target))
+ {
+ contextNo = contextScorer.doc();
}
- docNo = target - 1;
- return next();
- }
+ else
+ {
+ contextNo = -1;
+ }
+ }
+ docNo = target - 1;
+ return next();
+ }
- /**
- * @throws UnsupportedOperationException always
- */
- public Explanation explain(int doc) throws IOException {
- throw new UnsupportedOperationException();
- }
- }
+ /**
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Explanation explain(int doc) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ParentAxisQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ParentAxisQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/ParentAxisQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,12 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.HitCollector;
@@ -30,339 +24,402 @@
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Similarity;
import org.apache.lucene.search.Weight;
-
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.impl.core.query.lucene.hits.Hits;
import org.exoplatform.services.jcr.impl.core.query.lucene.hits.ScorerHits;
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
/**
* <code>ParentAxisQuery</code> selects the parent nodes of a context query.
*/
-class ParentAxisQuery extends Query {
+class ParentAxisQuery extends Query
+{
- /**
- * Default score is 1.0f.
- */
- private static final Float DEFAULT_SCORE = new Float(1.0f);
+ /**
+ * Default score is 1.0f.
+ */
+ private static final Float DEFAULT_SCORE = new Float(1.0f);
- /**
- * The context query
- */
- private final Query contextQuery;
+ /**
+ * The context query
+ */
+ private final Query contextQuery;
- /**
- * The nameTest to apply on the parent axis, or <code>null</code> if any
- * parent node should be selected.
- */
- private final InternalQName nameTest;
+ /**
+ * The nameTest to apply on the parent axis, or <code>null</code> if any
+ * parent node should be selected.
+ */
+ private final InternalQName nameTest;
- /**
- * The index format version.
- */
- private final IndexFormatVersion version;
+ /**
+ * The index format version.
+ */
+ private final IndexFormatVersion version;
- /**
- * The internal namespace mappings.
- */
- private final NamespaceMappings nsMappings;
+ /**
+ * The internal namespace mappings.
+ */
+ private final NamespaceMappings nsMappings;
- /**
- * The scorer of the context query
- */
- private Scorer contextScorer;
+ /**
+ * The scorer of the context query
+ */
+ private Scorer contextScorer;
- /**
- * Creates a new <code>ParentAxisQuery</code> based on a
- * <code>context</code> query.
- *
- * @param context the context for this query.
- * @param nameTest a name test or <code>null</code> if any parent node is
- * selected.
- * @param version the index format version.
- * @param nsMappings the internal namespace mappings.
- */
- ParentAxisQuery(Query context, InternalQName nameTest,
- IndexFormatVersion version, NamespaceMappings nsMappings) {
- this.contextQuery = context;
- this.nameTest = nameTest;
- this.version = version;
- this.nsMappings = nsMappings;
- }
+ /**
+ * Creates a new <code>ParentAxisQuery</code> based on a
+ * <code>context</code> query.
+ *
+ * @param context the context for this query.
+ * @param nameTest a name test or <code>null</code> if any parent node is
+ * selected.
+ * @param version the index format version.
+ * @param nsMappings the internal namespace mappings.
+ */
+ ParentAxisQuery(Query context, InternalQName nameTest, IndexFormatVersion version, NamespaceMappings nsMappings)
+ {
+ this.contextQuery = context;
+ this.nameTest = nameTest;
+ this.version = version;
+ this.nsMappings = nsMappings;
+ }
- /**
- * Creates a <code>Weight</code> instance for this query.
- *
- * @param searcher the <code>Searcher</code> instance to use.
- * @return a <code>ParentAxisWeight</code>.
- */
- protected Weight createWeight(Searcher searcher) {
- return new ParentAxisWeight(searcher);
- }
+ /**
+ * Creates a <code>Weight</code> instance for this query.
+ *
+ * @param searcher the <code>Searcher</code> instance to use.
+ * @return a <code>ParentAxisWeight</code>.
+ */
+ @Override
+ public Weight createWeight(Searcher searcher)
+ {
+ return new ParentAxisWeight(searcher);
+ }
- /**
- * {@inheritDoc}
- */
- public void extractTerms(Set terms) {
- contextQuery.extractTerms(terms);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void extractTerms(Set terms)
+ {
+ contextQuery.extractTerms(terms);
+ }
- /**
- * {@inheritDoc}
- */
- public Query rewrite(IndexReader reader) throws IOException {
- Query cQuery = contextQuery.rewrite(reader);
- if (cQuery == contextQuery) {
- return this;
- } else {
- return new ParentAxisQuery(cQuery, nameTest, version, nsMappings);
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Query rewrite(IndexReader reader) throws IOException
+ {
+ Query cQuery = contextQuery.rewrite(reader);
+ if (cQuery == contextQuery)
+ {
+ return this;
+ }
+ else
+ {
+ return new ParentAxisQuery(cQuery, nameTest, version, nsMappings);
+ }
+ }
- /**
- * Always returns 'ParentAxisQuery'.
- *
- * @param field the name of a field.
- * @return 'ParentAxisQuery'.
- */
- public String toString(String field) {
- return "ParentAxisQuery "+"nameTest="+(nameTest!=null?nameTest.toString():"null")+" contextQuery="+contextQuery.toString();
- }
+ /**
+ * Always returns 'ParentAxisQuery'.
+ *
+ * @param field the name of a field.
+ * @return 'ParentAxisQuery'.
+ */
+ @Override
+ public String toString(String field)
+ {
+ return "ParentAxisQuery " + "nameTest=" + (nameTest != null ? nameTest.toString() : "null") + " contextQuery="
+ + contextQuery.toString();
+ }
- //-----------------------< ParentAxisWeight >-------------------------------
+ //-----------------------< ParentAxisWeight >-------------------------------
- /**
- * The <code>Weight</code> implementation for this <code>ParentAxisQuery</code>.
- */
- private class ParentAxisWeight implements Weight {
+ /**
+ * The <code>Weight</code> implementation for this <code>ParentAxisQuery</code>.
+ */
+ private class ParentAxisWeight extends Weight
+ {
- /**
- * The searcher in use
- */
- private final Searcher searcher;
+ /**
+ * The searcher in use
+ */
+ private final Searcher searcher;
- /**
- * Creates a new <code>ParentAxisWeight</code> instance using
- * <code>searcher</code>.
- *
- * @param searcher a <code>Searcher</code> instance.
- */
- private ParentAxisWeight(Searcher searcher) {
- this.searcher = searcher;
- }
+ /**
+ * Creates a new <code>ParentAxisWeight</code> instance using
+ * <code>searcher</code>.
+ *
+ * @param searcher a <code>Searcher</code> instance.
+ */
+ private ParentAxisWeight(Searcher searcher)
+ {
+ this.searcher = searcher;
+ }
- /**
- * Returns this <code>ParentAxisQuery</code>.
- *
- * @return this <code>ParentAxisQuery</code>.
- */
- public Query getQuery() {
- return ParentAxisQuery.this;
- }
+ /**
+ * Returns this <code>ParentAxisQuery</code>.
+ *
+ * @return this <code>ParentAxisQuery</code>.
+ */
+ @Override
+ public Query getQuery()
+ {
+ return ParentAxisQuery.this;
+ }
- /**
- * {@inheritDoc}
- */
- public float getValue() {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getValue()
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public float sumOfSquaredWeights() throws IOException {
- return 1.0f;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float sumOfSquaredWeights() throws IOException
+ {
+ return 1.0f;
+ }
- /**
- * {@inheritDoc}
- */
- public void normalize(float norm) {
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void normalize(float norm)
+ {
+ }
- /**
- * Creates a scorer for this <code>ParentAxisQuery</code>.
- *
- * @param reader a reader for accessing the index.
- * @return a <code>ParentAxisScorer</code>.
- * @throws IOException if an error occurs while reading from the index.
- */
- public Scorer scorer(IndexReader reader) throws IOException {
- contextScorer = contextQuery.weight(searcher).scorer(reader);
- HierarchyResolver resolver = (HierarchyResolver) reader;
- return new ParentAxisScorer(searcher.getSimilarity(),
- reader, searcher, resolver);
- }
+ /**
+ * Creates a scorer for this <code>ParentAxisQuery</code>.
+ *
+ * @param reader a reader for accessing the index.
+ * @return a <code>ParentAxisScorer</code>.
+ * @throws IOException if an error occurs while reading from the index.
+ */
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException
+ {
+ contextScorer = contextQuery.weight(searcher).scorer(reader, scoreDocsInOrder, topScorer);
+ HierarchyResolver resolver = (HierarchyResolver)reader;
+ return new ParentAxisScorer(searcher.getSimilarity(), reader, searcher, resolver);
+ }
- /**
- * {@inheritDoc}
- */
- public Explanation explain(IndexReader reader, int doc) throws IOException {
- return new Explanation();
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException
+ {
+ return new Explanation();
+ }
+ }
- //--------------------------< ParentAxisScorer >----------------------------
+ //--------------------------< ParentAxisScorer >----------------------------
- /**
- * Implements a <code>Scorer</code> for this <code>ParentAxisQuery</code>.
- */
- private class ParentAxisScorer extends Scorer {
+ /**
+ * Implements a <code>Scorer</code> for this <code>ParentAxisQuery</code>.
+ */
+ private class ParentAxisScorer extends Scorer
+ {
- /**
- * An <code>IndexReader</code> to access the index.
- */
- private final IndexReader reader;
+ /**
+ * An <code>IndexReader</code> to access the index.
+ */
+ private final IndexReader reader;
- /**
- * The <code>HierarchyResolver</code> of the index.
- */
- private final HierarchyResolver hResolver;
+ /**
+ * The <code>HierarchyResolver</code> of the index.
+ */
+ private final HierarchyResolver hResolver;
- /**
- * The searcher instance.
- */
- private final Searcher searcher;
+ /**
+ * The searcher instance.
+ */
+ private final Searcher searcher;
- /**
- * BitSet storing the id's of selected documents
- */
- private BitSet hits;
+ /**
+ * BitSet storing the id's of selected documents
+ */
+ private BitSet hits;
- /**
- * Map that contains the scores from matching documents from the context
- * query. To save memory only scores that are not equal to 1.0f are put
- * to this map.
- * <p/>
- * key=[Integer] id of selected document from context query<br>
- * value=[Float] score for that document
- */
- private final Map scores = new HashMap();
+ /**
+ * Map that contains the scores from matching documents from the context
+ * query. To save memory only scores that are not equal to 1.0f are put
+ * to this map.
+ * <p/>
+ * key=[Integer] id of selected document from context query<br>
+ * value=[Float] score for that document
+ */
+ private final Map scores = new HashMap();
- /**
- * The next document id to return
- */
- private int nextDoc = -1;
+ /**
+ * The next document id to return
+ */
+ private int nextDoc = -1;
- /**
- * Creates a new <code>ParentAxisScorer</code>.
- *
- * @param similarity the <code>Similarity</code> instance to use.
- * @param reader for index access.
- * @param searcher the index searcher.
- * @param resolver the hierarchy resolver.
- */
- protected ParentAxisScorer(Similarity similarity,
- IndexReader reader,
- Searcher searcher,
- HierarchyResolver resolver) {
- super(similarity);
- this.reader = reader;
- this.searcher = searcher;
- this.hResolver = resolver;
- }
+ /**
+ * Creates a new <code>ParentAxisScorer</code>.
+ *
+ * @param similarity the <code>Similarity</code> instance to use.
+ * @param reader for index access.
+ * @param searcher the index searcher.
+ * @param resolver the hierarchy resolver.
+ */
+ protected ParentAxisScorer(Similarity similarity, IndexReader reader, Searcher searcher,
+ HierarchyResolver resolver)
+ {
+ super(similarity);
+ this.reader = reader;
+ this.searcher = searcher;
+ this.hResolver = resolver;
+ }
- /**
- * {@inheritDoc}
- */
- public boolean next() throws IOException {
- calculateParent();
- nextDoc = hits.nextSetBit(nextDoc + 1);
- return nextDoc > -1;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean next() throws IOException
+ {
+ calculateParent();
+ nextDoc = hits.nextSetBit(nextDoc + 1);
+ return nextDoc > -1;
+ }
- /**
- * {@inheritDoc}
- */
- public int doc() {
- return nextDoc;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int doc()
+ {
+ return nextDoc;
+ }
- /**
- * {@inheritDoc}
- */
- public float score() throws IOException {
- Float score = (Float) scores.get(new Integer(nextDoc));
- if (score == null) {
- score = DEFAULT_SCORE;
- }
- return score.floatValue();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float score() throws IOException
+ {
+ Float score = (Float)scores.get(new Integer(nextDoc));
+ if (score == null)
+ {
+ score = DEFAULT_SCORE;
+ }
+ return score.floatValue();
+ }
- /**
- * {@inheritDoc}
- */
- public boolean skipTo(int target) throws IOException {
- calculateParent();
- nextDoc = hits.nextSetBit(target);
- return nextDoc > -1;
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean skipTo(int target) throws IOException
+ {
+ calculateParent();
+ nextDoc = hits.nextSetBit(target);
+ return nextDoc > -1;
+ }
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException this implementation always
- * throws an <code>UnsupportedOperationException</code>.
- */
- public Explanation explain(int doc) throws IOException {
- throw new UnsupportedOperationException();
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException this implementation always
+ * throws an <code>UnsupportedOperationException</code>.
+ */
+ @Override
+ public Explanation explain(int doc) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
- private void calculateParent() throws IOException {
- if (hits == null) {
- hits = new BitSet(reader.maxDoc());
+ private void calculateParent() throws IOException
+ {
+ if (hits == null)
+ {
+ hits = new BitSet(reader.maxDoc());
- final IOException[] ex = new IOException[1];
- contextScorer.score(new HitCollector() {
+ final IOException[] ex = new IOException[1];
+ contextScorer.score(new HitCollector()
+ {
- private int[] docs = new int[1];
+ private int[] docs = new int[1];
- public void collect(int doc, float score) {
- try {
- docs = hResolver.getParents(doc, docs);
- if (docs.length == 1) {
- // optimize single value
- hits.set(docs[0]);
- if (score != DEFAULT_SCORE.floatValue()) {
- scores.put(new Integer(docs[0]), new Float(score));
- }
- } else {
- for (int i = 0; i < docs.length; i++) {
- hits.set(docs[i]);
- if (score != DEFAULT_SCORE.floatValue()) {
- scores.put(new Integer(docs[i]), new Float(score));
- }
- }
- }
- } catch (IOException e) {
- ex[0] = e;
+ @Override
+ public void collect(int doc, float score)
+ {
+ try
+ {
+ docs = hResolver.getParents(doc, docs);
+ if (docs.length == 1)
+ {
+ // optimize single value
+ hits.set(docs[0]);
+ if (score != DEFAULT_SCORE.floatValue())
+ {
+ scores.put(new Integer(docs[0]), new Float(score));
}
- }
- });
+ }
+ else
+ {
+ for (int i = 0; i < docs.length; i++)
+ {
+ hits.set(docs[i]);
+ if (score != DEFAULT_SCORE.floatValue())
+ {
+ scores.put(new Integer(docs[i]), new Float(score));
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ ex[0] = e;
+ }
+ }
+ });
- if (ex[0] != null) {
- throw ex[0];
- }
+ if (ex[0] != null)
+ {
+ throw ex[0];
+ }
- // filter out documents that do not match the name test
- if (nameTest != null) {
- Query nameQuery = new NameQuery(nameTest, version, nsMappings);
- Hits nameHits = new ScorerHits(nameQuery.weight(searcher).scorer(reader));
- for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
- int doc = nameHits.skipTo(i);
- if (doc == -1) {
- // no more name tests, clear remaining
- hits.clear(i, hits.length());
- } else {
- // assert doc >= i
- if (doc > i) {
- // clear hits
- hits.clear(i, doc);
- i = doc;
- }
- }
- }
- }
+ // filter out documents that do not match the name test
+ if (nameTest != null)
+ {
+ Query nameQuery = new NameQuery(nameTest, version, nsMappings);
+ Hits nameHits = new ScorerHits(nameQuery.weight(searcher).scorer(reader, true, false));
+ for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1))
+ {
+ int doc = nameHits.skipTo(i);
+ if (doc == -1)
+ {
+ // no more name tests, clear remaining
+ hits.clear(i, hits.length());
+ }
+ else
+ {
+ // assert doc >= i
+ if (doc > i)
+ {
+ // clear hits
+ hits.clear(i, doc);
+ i = doc;
+ }
+ }
+ }
}
- }
- }
+ }
+ }
+ }
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/QueryHitsQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/QueryHitsQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/QueryHitsQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,13 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
@@ -35,6 +28,13 @@
import org.apache.lucene.search.Weight;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
/**
* <code>QueryHitsQuery</code> exposes a {@link QueryHits} implementation again
* as a Lucene Query.
@@ -58,21 +58,24 @@
/**
* {@inheritDoc}
*/
- protected Weight createWeight(Searcher searcher) throws IOException {
+ @Override
+ public Weight createWeight(Searcher searcher) throws IOException {
return new QueryHitsQueryWeight(searcher.getSimilarity());
}
/**
* {@inheritDoc}
*/
- public String toString(String field) {
+ @Override
+ public String toString(String field) {
return "QueryHitsQuery";
}
/**
* {@inheritDoc}
*/
- public void extractTerms(Set terms) {
+ @Override
+ public void extractTerms(Set terms) {
// no terms
}
@@ -96,7 +99,7 @@
/**
* The Weight implementation for this query.
*/
- public class QueryHitsQueryWeight implements Weight {
+ public class QueryHitsQueryWeight extends Weight {
/**
* The similarity.
@@ -115,41 +118,48 @@
/**
* {@inheritDoc}
*/
- public Query getQuery() {
+ @Override
+ public Query getQuery() {
return QueryHitsQuery.this;
}
/**
* {@inheritDoc}
*/
- public float getValue() {
+ @Override
+ public float getValue() {
return 1.0f;
}
/**
* {@inheritDoc}
*/
- public float sumOfSquaredWeights() throws IOException {
+ @Override
+ public float sumOfSquaredWeights() throws IOException {
return 1.0f;
}
/**
* {@inheritDoc}
*/
- public void normalize(float norm) {
+ @Override
+ public void normalize(float norm) {
}
/**
* {@inheritDoc}
*/
- public Scorer scorer(IndexReader reader) throws IOException {
+ @Override
+ public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException {
+ // TODO: use arguments!
return new QueryHitsQueryScorer(reader, similarity);
}
/**
* {@inheritDoc}
*/
- public Explanation explain(IndexReader reader, int doc) throws IOException {
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException {
return new Explanation();
}
}
@@ -215,7 +225,8 @@
/**
* {@inheritDoc}
*/
- public boolean next() throws IOException {
+ @Override
+ public boolean next() throws IOException {
if (docs.hasNext()) {
currentDoc = (Integer) docs.next();
return true;
@@ -226,21 +237,24 @@
/**
* {@inheritDoc}
*/
- public int doc() {
+ @Override
+ public int doc() {
return currentDoc.intValue();
}
/**
* {@inheritDoc}
*/
- public float score() throws IOException {
+ @Override
+ public float score() throws IOException {
return ((Float) scores.get(currentDoc)).floatValue();
}
/**
* {@inheritDoc}
*/
- public boolean skipTo(int target) throws IOException {
+ @Override
+ public boolean skipTo(int target) throws IOException {
do {
if (!next()) {
return false;
@@ -252,7 +266,8 @@
/**
* {@inheritDoc}
*/
- public Explanation explain(int doc) throws IOException {
+ @Override
+ public Explanation explain(int doc) throws IOException {
return new Explanation();
}
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RangeQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RangeQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RangeQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,15 +16,6 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
@@ -37,6 +28,15 @@
import org.apache.lucene.search.Similarity;
import org.apache.lucene.search.Weight;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Implements a lucene range query.
*/
@@ -121,7 +121,8 @@
* @return the rewritten query or this query if rewriting is not possible.
* @throws IOException if an error occurs.
*/
- public Query rewrite(IndexReader reader) throws IOException {
+ @Override
+ public Query rewrite(IndexReader reader) throws IOException {
if (transform == TRANSFORM_NONE) {
return new ConstantScoreRangeQuery(lowerTerm.field(),
lowerTerm.text(), upperTerm.text(), inclusive,
@@ -139,7 +140,8 @@
* @param searcher the searcher to use for the <code>Weight</code>.
* @return the <code>Weigth</code> for this query.
*/
- protected Weight createWeight(Searcher searcher) {
+ @Override
+ public Weight createWeight(Searcher searcher) {
return new RangeQueryWeight(searcher);
}
@@ -148,7 +150,8 @@
* @param field the field name for which to create a string representation.
* @return a string representation of this query.
*/
- public String toString(String field) {
+ @Override
+ public String toString(String field) {
StringBuffer buffer = new StringBuffer();
if (!getField().equals(field)) {
buffer.append(getField());
@@ -169,7 +172,8 @@
/**
* {@inheritDoc}
*/
- public void extractTerms(Set terms) {
+ @Override
+ public void extractTerms(Set terms) {
// cannot extract terms
}
@@ -203,7 +207,8 @@
* @param reader index reader
* @return a {@link RangeQueryScorer} instance
*/
- protected Scorer createScorer(IndexReader reader) {
+ @Override
+ protected Scorer createScorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) {
return new RangeQueryScorer(searcher.getSimilarity(), reader);
};
@@ -212,34 +217,39 @@
*
* @return this <code>RangeQuery</code>.
*/
- public Query getQuery() {
+ @Override
+ public Query getQuery() {
return RangeQuery.this;
}
/**
* {@inheritDoc}
*/
- public float getValue() {
+ @Override
+ public float getValue() {
return 1.0f;
}
/**
* {@inheritDoc}
*/
- public float sumOfSquaredWeights() throws IOException {
+ @Override
+ public float sumOfSquaredWeights() throws IOException {
return 1.0f;
}
/**
* {@inheritDoc}
*/
- public void normalize(float norm) {
+ @Override
+ public void normalize(float norm) {
}
/**
* {@inheritDoc}
*/
- public Explanation explain(IndexReader reader, int doc) throws IOException {
+ @Override
+ public Explanation explain(IndexReader reader, int doc) throws IOException {
return new Explanation();
}
}
@@ -321,7 +331,8 @@
/**
* {@inheritDoc}
*/
- public boolean next() throws IOException {
+ @Override
+ public boolean next() throws IOException {
calculateHits();
nextDoc = hits.nextSetBit(nextDoc + 1);
return nextDoc > -1;
@@ -330,21 +341,24 @@
/**
* {@inheritDoc}
*/
- public int doc() {
+ @Override
+ public int doc() {
return nextDoc;
}
/**
* {@inheritDoc}
*/
- public float score() {
+ @Override
+ public float score() {
return 1.0f;
}
/**
* {@inheritDoc}
*/
- public boolean skipTo(int target) throws IOException {
+ @Override
+ public boolean skipTo(int target) throws IOException {
calculateHits();
nextDoc = hits.nextSetBit(target);
return nextDoc > -1;
@@ -354,7 +368,8 @@
* Returns an empty Explanation object.
* @return an empty Explanation object.
*/
- public Explanation explain(int doc) {
+ @Override
+ public Explanation explain(int doc) {
return new Explanation();
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RefCountingIndexReader.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RefCountingIndexReader.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RefCountingIndexReader.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,11 +16,11 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.apache.lucene.index.FilterIndexReader;
import org.apache.lucene.index.IndexReader;
+import java.io.IOException;
+
/**
* <code>RefCountingIndexReader</code>...
*/
@@ -48,7 +48,8 @@
/**
* @return the current reference count value.
*/
- synchronized int getRefCount() {
+ @Override
+ public synchronized int getRefCount() {
return refCount;
}
@@ -65,7 +66,8 @@
//-----------------------< FilterIndexReader >--------------------------
- protected void doClose() throws IOException {
+ @Override
+ protected void doClose() throws IOException {
Util.closeOrRelease(in);
}
}
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -2745,7 +2745,7 @@
IndexSearcher searcher = new IndexSearcher(reader);
searcher.setSimilarity(getSimilarity());
- return new LuceneQueryHits(reader, searcher, query);
+ return new LuceneQueryHits(reader, searcher, query, true, false);
}
/**
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SingleIndex.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SingleIndex.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SingleIndex.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -27,11 +27,9 @@
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
-import org.apache.lucene.store.RAMDirectory;
import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.impl.core.query.IndexingTree;
-
import org.exoplatform.services.jcr.util.IdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,9 +39,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
/**
@@ -99,6 +95,7 @@
log.info(dir);
//FSDirectory.getDirectory(indexDirectory2);
this.writer = new IndexWriter(directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED);
+ this.writer.setRAMBufferSizeMB(1);
this.reader = IndexReader.open(directory, true);
this.cache = new DocNumberCache(handler.getCacheSize());
@@ -175,6 +172,16 @@
private class JcrSingleIndexReader extends FilterIndexReader implements HierarchyResolver
{
+ @Override
+ public IndexReader[] getSequentialSubReaders()
+ {
+ // This method returns null, so Lucene internals doesn't explode this reader on it's subreaders.
+ // This is used to retrieve this index reader as HierarchyResolver in ChildAxisQuery. If this method
+ // is not overridden with null-returning one, then ClassCast exception is thrown.
+ // This solution confirmed via Lucene mailing-list on May 27 2010.
+ return null;
+ }
+
/**
* @param reader
*/
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/WildcardQuery.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/WildcardQuery.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/WildcardQuery.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -129,10 +129,12 @@
* @return the rewritten query.
* @throws IOException if an error occurs while reading from the index.
*/
+ @Override
public Query rewrite(IndexReader reader) throws IOException
{
Query stdWildcardQuery = new MultiTermQuery(new Term(field, pattern))
{
+ @Override
protected FilteredTermEnum getEnum(IndexReader reader) throws IOException
{
return new WildcardTermEnum(reader, field, propName, pattern, transform);
@@ -157,7 +159,8 @@
* @param searcher the searcher to use for the <code>Weight</code>.
* @return the <code>Weigth</code> for this query.
*/
- protected Weight createWeight(Searcher searcher)
+ @Override
+ public Weight createWeight(Searcher searcher)
{
return new WildcardQueryWeight(searcher);
}
@@ -168,6 +171,7 @@
* @param field the field name for which to create a string representation.
* @return a string representation of this query.
*/
+ @Override
public String toString(String field)
{
return propName + ":" + pattern;
@@ -176,6 +180,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void extractTerms(Set terms)
{
if (multiTermQuery != null)
@@ -207,7 +212,8 @@
* @param reader index reader
* @return a {@link WildcardQueryScorer} instance
*/
- protected Scorer createScorer(IndexReader reader)
+ @Override
+ protected Scorer createScorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer)
{
return new WildcardQueryScorer(searcher.getSimilarity(), reader);
}
@@ -217,6 +223,7 @@
*
* @return this <code>WildcardQuery</code>.
*/
+ @Override
public Query getQuery()
{
return WildcardQuery.this;
@@ -225,6 +232,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float getValue()
{
return 1.0f;
@@ -233,6 +241,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float sumOfSquaredWeights() throws IOException
{
return 1.0f;
@@ -241,6 +250,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void normalize(float norm)
{
}
@@ -248,6 +258,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public Explanation explain(IndexReader reader, int doc) throws IOException
{
return new Explanation();
@@ -326,6 +337,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean next() throws IOException
{
calculateHits();
@@ -336,6 +348,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public int doc()
{
return nextDoc;
@@ -344,6 +357,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public float score()
{
return 1.0f;
@@ -352,6 +366,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean skipTo(int target) throws IOException
{
calculateHits();
@@ -363,6 +378,7 @@
* Returns an empty Explanation object.
* @return an empty Explanation object.
*/
+ @Override
public Explanation explain(int doc)
{
return new Explanation();
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/directory/FSDirectoryManager.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/directory/FSDirectoryManager.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/directory/FSDirectoryManager.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -16,15 +16,15 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene.directory;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.NativeFSLockFactory;
import org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+
/**
* <code>FSDirectoryManager</code> implements a directory manager for
* {@link FSDirectory} instances.
@@ -61,7 +61,15 @@
} else {
dir = new File(baseDir, name);
}
- return FSDirectory.getDirectory(dir, new NativeFSLockFactory(dir));
+ // FSDirectory itself doesnt create dirs now
+ if (!dir.exists())
+ {
+ if (!dir.mkdirs())
+ {
+ throw new IOException("Cannot create directory: " + dir);
+ }
+ }
+ return FSDirectory.open(dir, new NativeFSLockFactory(dir));
}
/**
Modified: jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java
===================================================================
--- jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java 2010-05-26 14:43:44 UTC (rev 2439)
+++ jcr/branches/1.12-LIC-709/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java 2010-05-28 06:54:18 UTC (rev 2440)
@@ -33,88 +33,105 @@
* <code>DirectoryManagerTest</code> performs tests on directory manager
* implementations.
*/
-public class DirectoryManagerTest extends TestCase {
+public class DirectoryManagerTest extends TestCase
+{
- private static final Collection IMPLEMENTATIONS = Arrays
- .asList(new Class[] { FSDirectoryManager.class,
- RAMDirectoryManager.class });
+ private static final Collection IMPLEMENTATIONS =
+ Arrays.asList(new Class[]{FSDirectoryManager.class, RAMDirectoryManager.class});
- private static final SearchIndex INDEX = new SearchIndex();
+ private static final SearchIndex INDEX = new SearchIndex();
- private static final String TEST = "test";
+ private static final String TEST = "test";
- private static final String RENAMED = "renamed";
+ private static final String RENAMED = "renamed";
- static {
- INDEX.setPath(new File(new File("target"), "directory-factory-test")
- .getAbsolutePath());
- }
+ static
+ {
+ File dst = new File(new File("target"), "directory-factory-test");
+ dst.mkdirs();
+ INDEX.setPath(dst.getAbsolutePath());
+ }
- protected void tearDown() throws Exception {
- new File(INDEX.getPath(), TEST).delete();
- new File(INDEX.getPath(), RENAMED).delete();
- }
+ @Override
+ protected void tearDown() throws Exception
+ {
+// new File(INDEX.getPath(), TEST).delete();
+// new File(INDEX.getPath(), RENAMED).delete();
+ }
- public void testHasDirectory() throws Exception {
- execute(new Callable() {
- public void call(DirectoryManager directoryManager)
- throws Exception {
- Directory dir = directoryManager.getDirectory(TEST);
- assertTrue(directoryManager.hasDirectory(TEST));
- dir.close();
- }
- });
- }
+ public void testHasDirectory() throws Exception
+ {
+ execute(new Callable()
+ {
+ public void call(DirectoryManager directoryManager) throws Exception
+ {
+ Directory dir = directoryManager.getDirectory(TEST);
+ assertTrue("Impl:" + directoryManager.getClass().getName(), directoryManager.hasDirectory(TEST));
+ dir.close();
+ }
+ });
+ }
- public void testDelete() throws Exception {
- execute(new Callable() {
- public void call(DirectoryManager directoryManager)
- throws Exception {
- directoryManager.getDirectory(TEST).close();
- directoryManager.delete(TEST);
- assertFalse(directoryManager.hasDirectory(TEST));
- }
- });
- }
+ public void testDelete() throws Exception
+ {
+ execute(new Callable()
+ {
+ public void call(DirectoryManager directoryManager) throws Exception
+ {
+ directoryManager.getDirectory(TEST).close();
+ directoryManager.delete(TEST);
+ assertFalse("Impl:" + directoryManager.getClass().getName(), directoryManager.hasDirectory(TEST));
+ }
+ });
+ }
- public void testGetDirectoryNames() throws Exception {
- execute(new Callable() {
- public void call(DirectoryManager directoryManager)
- throws Exception {
- directoryManager.getDirectory(TEST).close();
- assertTrue(Arrays.asList(directoryManager.getDirectoryNames())
- .contains(TEST));
- }
- });
- }
+ public void testGetDirectoryNames() throws Exception
+ {
+ execute(new Callable()
+ {
+ public void call(DirectoryManager directoryManager) throws Exception
+ {
+ directoryManager.getDirectory(TEST).close();
+ assertTrue("Impl:" + directoryManager.getClass().getName(), Arrays.asList(directoryManager.getDirectoryNames()).contains(TEST));
+ }
+ });
+ }
- public void testRename() throws Exception {
- execute(new Callable() {
- public void call(DirectoryManager directoryManager)
- throws Exception {
- directoryManager.getDirectory(TEST).close();
- directoryManager.rename(TEST, RENAMED);
- assertTrue(directoryManager.hasDirectory(RENAMED));
- assertFalse(directoryManager.hasDirectory(TEST));
- }
- });
- }
+ public void testRename() throws Exception
+ {
+ execute(new Callable()
+ {
+ public void call(DirectoryManager directoryManager) throws Exception
+ {
+ directoryManager.getDirectory(TEST).close();
+ directoryManager.rename(TEST, RENAMED);
+ assertTrue("Impl:" + directoryManager.getClass().getName(), directoryManager.hasDirectory(RENAMED));
+ assertFalse("Impl:" + directoryManager.getClass().getName(), directoryManager.hasDirectory(TEST));
+ }
+ });
+ }
- private void execute(Callable callable) throws Exception {
- for (Iterator it = IMPLEMENTATIONS.iterator(); it.hasNext();) {
- Class clazz = (Class) it.next();
- DirectoryManager dirMgr = (DirectoryManager) clazz.newInstance();
- dirMgr.init(INDEX);
- try {
- callable.call(dirMgr);
- } finally {
- dirMgr.dispose();
- }
- }
- }
+ private void execute(Callable callable) throws Exception
+ {
+ for (Iterator it = IMPLEMENTATIONS.iterator(); it.hasNext();)
+ {
+ Class clazz = (Class)it.next();
+ DirectoryManager dirMgr = (DirectoryManager)clazz.newInstance();
+ dirMgr.init(INDEX);
+ try
+ {
+ callable.call(dirMgr);
+ }
+ finally
+ {
+ dirMgr.dispose();
+ }
+ }
+ }
- private interface Callable {
+ private interface Callable
+ {
- public void call(DirectoryManager directoryManager) throws Exception;
- }
+ public void call(DirectoryManager directoryManager) throws Exception;
+ }
}
13 years, 11 months
exo-jcr SVN: r2439 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-05-26 10:43:44 -0400 (Wed, 26 May 2010)
New Revision: 2439
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
Log:
EXOJCR-735 : Problem with "not using configuration from persister" was fixed.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-26 14:31:13 UTC (rev 2438)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/config/RepositoryServiceConfigurationImpl.java 2010-05-26 14:43:44 UTC (rev 2439)
@@ -251,7 +251,7 @@
{
try
{
- if (configExtensionPaths.isEmpty())
+ if (configExtensionPaths.isEmpty() || (configurationPersister != null && configurationPersister.hasConfig()))
{
initFromStream(configurationService.getInputStream(param.getValue()));
}
13 years, 11 months
exo-jcr SVN: r2438 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc: db and 2 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-05-26 10:31:13 -0400 (Wed, 26 May 2010)
New Revision: 2438
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
Log:
EXOJCR-754: close PreparedStatement on connection close
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -121,6 +121,68 @@
protected final WriteValueHelper writeValueHelper = new WriteValueHelper();
+ // All statements should be closed in cloaseStatements() method.
+
+ protected PreparedStatement findItemById;
+
+ protected PreparedStatement findItemByPath;
+
+ protected PreparedStatement findItemByName;
+
+ protected PreparedStatement findChildPropertyByPath;
+
+ protected PreparedStatement findPropertyByName;
+
+ protected PreparedStatement findDescendantNodes;
+
+ protected PreparedStatement findDescendantProperties;
+
+ protected PreparedStatement findReferences;
+
+ protected PreparedStatement findValuesByPropertyId;
+
+ protected PreparedStatement findValuesStorageDescriptorsByPropertyId;
+
+ protected PreparedStatement findValuesDataByPropertyId;
+
+ protected PreparedStatement findValueByPropertyIdOrderNumber;
+
+ protected PreparedStatement findNodesByParentId;
+
+ protected PreparedStatement findNodesCountByParentId;
+
+ protected PreparedStatement findPropertiesByParentId;
+
+ protected PreparedStatement insertItem;
+
+ protected PreparedStatement insertNode;
+
+ protected PreparedStatement insertProperty;
+
+ protected PreparedStatement insertReference;
+
+ protected PreparedStatement insertValue;
+
+ protected PreparedStatement updateItem;
+
+ protected PreparedStatement updateItemPath;
+
+ protected PreparedStatement updateNode;
+
+ protected PreparedStatement updateProperty;
+
+ protected PreparedStatement deleteItem;
+
+ protected PreparedStatement deleteNode;
+
+ protected PreparedStatement deleteProperty;
+
+ protected PreparedStatement deleteReference;
+
+ protected PreparedStatement deleteValue;
+
+ protected PreparedStatement renameNode;
+
/**
* Read-only flag, if true the connection is marked as READ-ONLY.
*/
@@ -303,6 +365,8 @@
checkIfOpened();
try
{
+ closeStatements();
+
// If READ-ONLY status back it to READ-WRITE (we assume it was original state)
if (readOnly)
{
@@ -318,6 +382,164 @@
}
/**
+ * Close all statements.
+ *
+ * @throws SQLException
+ */
+ protected void closeStatements() throws SQLException
+ {
+ if (findItemById != null)
+ {
+ findItemById.close();
+ }
+
+ if (findItemByPath != null)
+ {
+ findItemByPath.close();
+ }
+
+ if (findItemByName != null)
+ {
+ findItemByName.close();
+ }
+
+ if (findChildPropertyByPath != null)
+ {
+ findChildPropertyByPath.close();
+ }
+
+ if (findPropertyByName != null)
+ {
+ findPropertyByName.close();
+ }
+
+ if (findDescendantNodes != null)
+ {
+ findDescendantNodes.close();
+ }
+
+ if (findDescendantProperties != null)
+ {
+ findDescendantProperties.close();
+ }
+
+ if (findReferences != null)
+ {
+ findReferences.close();
+ }
+
+ if (findValuesByPropertyId != null)
+ {
+ findValuesByPropertyId.close();
+ }
+
+ if (findValuesStorageDescriptorsByPropertyId != null)
+ {
+ findValuesStorageDescriptorsByPropertyId.close();
+ }
+
+ if (findValuesDataByPropertyId != null)
+ {
+ findValuesDataByPropertyId.close();
+ }
+
+ if (findValueByPropertyIdOrderNumber != null)
+ {
+ findValueByPropertyIdOrderNumber.close();
+ }
+
+ if (findNodesByParentId != null)
+ {
+ findNodesByParentId.close();
+ }
+
+ if (findNodesCountByParentId != null)
+ {
+ findNodesCountByParentId.close();
+ }
+
+ if (findPropertiesByParentId != null)
+ {
+ findPropertiesByParentId.close();
+ }
+
+ if (insertItem != null)
+ {
+ insertItem.close();
+ }
+
+ if (insertNode != null)
+ {
+ insertNode.close();
+ }
+
+ if (insertProperty != null)
+ {
+ insertProperty.close();
+ }
+
+ if (insertReference != null)
+ {
+ insertReference.close();
+ }
+
+ if (insertValue != null)
+ {
+ insertValue.close();
+ }
+
+ if (updateItem != null)
+ {
+ updateItem.close();
+ }
+
+ if (updateItemPath != null)
+ {
+ updateItemPath.close();
+ }
+
+ if (updateNode != null)
+ {
+ updateNode.close();
+ }
+
+ if (updateProperty != null)
+ {
+ updateProperty.close();
+ }
+
+ if (deleteItem != null)
+ {
+ deleteItem.close();
+ }
+
+ if (deleteNode != null)
+ {
+ deleteNode.close();
+ }
+
+ if (deleteProperty != null)
+ {
+ deleteProperty.close();
+ }
+
+ if (deleteReference != null)
+ {
+ deleteReference.close();
+ }
+
+ if (deleteValue != null)
+ {
+ deleteValue.close();
+ }
+
+ if (renameNode != null)
+ {
+ renameNode.close();
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public final void commit() throws IllegalStateException, RepositoryException
@@ -948,7 +1170,7 @@
{
return traverseQPathSQ(cpid);
}
-
+
/**
* The method <code>traverseQPath</code> implemented thanks to simple queries. It allows
* to use Simple Queries instead of Complex Queries when complex queries are much slower such
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/MultiDbJDBCConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -31,7 +31,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@@ -51,66 +50,6 @@
public class MultiDbJDBCConnection extends JDBCStorageConnection
{
- protected PreparedStatement findItemById;
-
- protected PreparedStatement findItemByPath;
-
- protected PreparedStatement findItemByName;
-
- protected PreparedStatement findChildPropertyByPath;
-
- protected PreparedStatement findPropertyByName;
-
- protected PreparedStatement findDescendantNodes;
-
- protected PreparedStatement findDescendantProperties;
-
- protected PreparedStatement findReferences;
-
- protected PreparedStatement findValuesByPropertyId;
-
- protected PreparedStatement findValuesDataByPropertyId;
-
- protected PreparedStatement findValuesStorageDescriptorsByPropertyId;
-
- protected PreparedStatement findValueByPropertyIdOrderNumber;
-
- protected PreparedStatement findNodesByParentId;
-
- protected PreparedStatement findNodesCountByParentId;
-
- protected PreparedStatement findPropertiesByParentId;
-
- protected PreparedStatement insertNode;
-
- protected PreparedStatement insertProperty;
-
- protected PreparedStatement insertReference;
-
- protected PreparedStatement insertValue;
-
- protected PreparedStatement updateItem;
-
- protected PreparedStatement updateItemPath;
-
- protected PreparedStatement updateNode;
-
- protected PreparedStatement updateProperty;
-
- protected PreparedStatement updateValue;
-
- protected PreparedStatement deleteItem;
-
- protected PreparedStatement deleteNode;
-
- protected PreparedStatement deleteProperty;
-
- protected PreparedStatement deleteReference;
-
- protected PreparedStatement deleteValue;
-
- protected PreparedStatement renameNode;
-
/**
* Multidatabase JDBC Connection constructor.
*
@@ -183,10 +122,11 @@
FIND_VALUES_VSTORAGE_DESC_BY_PROPERTYID = "select distinct STORAGE_DESC from JCR_MVALUE where PROPERTY_ID=?";
- FIND_VALUE_BY_PROPERTYID_OREDERNUMB = "select DATA, STORAGE_DESC from JCR_MVALUE where PROPERTY_ID=? and ORDER_NUM=?";
+ FIND_VALUE_BY_PROPERTYID_OREDERNUMB =
+ "select DATA, STORAGE_DESC from JCR_MVALUE where PROPERTY_ID=? and ORDER_NUM=?";
FIND_NODES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?" + " order by N_ORDER_NUM";
-
+
FIND_NODES_COUNT_BY_PARENTID = "select count(ID) from JCR_MITEM" + " where I_CLASS=1 and PARENT_ID=?";
FIND_PROPERTIES_BY_PARENTID = "select * from JCR_MITEM" + " where I_CLASS=2 and PARENT_ID=?" + " order by ID";
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/db/SingleDbJDBCConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -30,7 +30,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@@ -49,68 +48,6 @@
public class SingleDbJDBCConnection extends JDBCStorageConnection
{
- protected PreparedStatement findItemById;
-
- protected PreparedStatement findItemByPath;
-
- protected PreparedStatement findItemByName;
-
- protected PreparedStatement findChildPropertyByPath;
-
- protected PreparedStatement findPropertyByName;
-
- protected PreparedStatement findDescendantNodes;
-
- protected PreparedStatement findDescendantProperties;
-
- protected PreparedStatement findReferences;
-
- protected PreparedStatement findValuesByPropertyId;
-
- protected PreparedStatement findValuesStorageDescriptorsByPropertyId;
-
- protected PreparedStatement findValuesDataByPropertyId;
-
- protected PreparedStatement findValueByPropertyIdOrderNumber;
-
- protected PreparedStatement findNodesByParentId;
-
- protected PreparedStatement findNodesCountByParentId;
-
- protected PreparedStatement findPropertiesByParentId;
-
- protected PreparedStatement insertItem;
-
- protected PreparedStatement insertNode;
-
- protected PreparedStatement insertProperty;
-
- protected PreparedStatement insertReference;
-
- protected PreparedStatement insertValue;
-
- protected PreparedStatement updateItem;
-
- protected PreparedStatement updateItemPath;
-
- protected PreparedStatement updateNode;
-
- protected PreparedStatement updateProperty;
-
- protected PreparedStatement updateValue;
-
- protected PreparedStatement deleteItem;
-
- protected PreparedStatement deleteNode;
-
- protected PreparedStatement deleteProperty;
-
- protected PreparedStatement deleteReference;
-
- protected PreparedStatement deleteValue;
-
- protected PreparedStatement renameNode;
-
/**
* Singledatabase JDBC Connection constructor.
*
@@ -190,7 +127,8 @@
FIND_VALUES_VSTORAGE_DESC_BY_PROPERTYID = "select distinct STORAGE_DESC from JCR_SVALUE where PROPERTY_ID=?";
- FIND_VALUE_BY_PROPERTYID_OREDERNUMB = "select DATA, STORAGE_DESC from JCR_SVALUE where PROPERTY_ID=? and ORDER_NUM=?";
+ FIND_VALUE_BY_PROPERTYID_OREDERNUMB =
+ "select DATA, STORAGE_DESC from JCR_SVALUE where PROPERTY_ID=? and ORDER_NUM=?";
FIND_NODES_BY_PARENTID =
"select * from JCR_SITEM" + " where I_CLASS=1 and CONTAINER_NAME=? and PARENT_ID=?" + " order by N_ORDER_NUM";
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -41,6 +41,7 @@
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
+import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -91,6 +92,14 @@
*/
protected String FIND_ITEM_QPATH_BY_ID_CQ;
+ protected PreparedStatement findNodesByParentIdCQ;
+
+ protected PreparedStatement findPropertiesByParentIdCQ;
+
+ protected PreparedStatement findNodeMainPropertiesByParentIdentifierCQ;
+
+ protected PreparedStatement findItemQPathByIdentifierCQ;
+
/**
* The comparator used to sort the value data
*/
@@ -657,6 +666,35 @@
return new QPath(qentries);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void closeStatements() throws SQLException
+ {
+ super.closeStatements();
+
+ if (findNodesByParentIdCQ != null)
+ {
+ findNodesByParentIdCQ.close();
+ }
+
+ if (findPropertiesByParentIdCQ != null)
+ {
+ findPropertiesByParentIdCQ.close();
+ }
+
+ if (findNodeMainPropertiesByParentIdentifierCQ != null)
+ {
+ findNodeMainPropertiesByParentIdentifierCQ.close();
+ }
+
+ if (findItemQPathByIdentifierCQ != null)
+ {
+ findItemQPathByIdentifierCQ.close();
+ }
+ }
+
protected abstract ResultSet findItemQPathByIdentifierCQ(String identifier) throws SQLException;
protected abstract ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -31,7 +31,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@@ -63,74 +62,6 @@
+ " V.ORDER_NUM, V.DATA, V.STORAGE_DESC from JCR_MITEM I LEFT OUTER JOIN JCR_MVALUE V ON (V.PROPERTY_ID=I.ID)"
+ " where I.I_CLASS=2 and I.PARENT_ID=? order by I.NAME";
- protected PreparedStatement findItemById;
-
- protected PreparedStatement findItemByPath;
-
- protected PreparedStatement findItemByName;
-
- protected PreparedStatement findChildPropertyByPath;
-
- protected PreparedStatement findPropertyByName;
-
- protected PreparedStatement findDescendantNodes;
-
- protected PreparedStatement findDescendantProperties;
-
- protected PreparedStatement findReferences;
-
- protected PreparedStatement findValuesByPropertyId;
-
- protected PreparedStatement findValuesDataByPropertyId;
-
- protected PreparedStatement findValuesStorageDescriptorsByPropertyId;
-
- protected PreparedStatement findValueByPropertyIdOrderNumber;
-
- protected PreparedStatement findNodesByParentId;
-
- protected PreparedStatement findNodesByParentIdCQ;
-
- protected PreparedStatement findNodesCountByParentId;
-
- protected PreparedStatement findPropertiesByParentId;
-
- protected PreparedStatement findPropertiesByParentIdCQ;
-
- protected PreparedStatement findNodeMainPropertiesByParentIdentifierCQ;
-
- protected PreparedStatement findItemQPathByIdentifierCQ;
-
- protected PreparedStatement insertNode;
-
- protected PreparedStatement insertProperty;
-
- protected PreparedStatement insertReference;
-
- protected PreparedStatement insertValue;
-
- protected PreparedStatement updateItem;
-
- protected PreparedStatement updateItemPath;
-
- protected PreparedStatement updateNode;
-
- protected PreparedStatement updateProperty;
-
- protected PreparedStatement updateValue;
-
- protected PreparedStatement deleteItem;
-
- protected PreparedStatement deleteNode;
-
- protected PreparedStatement deleteProperty;
-
- protected PreparedStatement deleteReference;
-
- protected PreparedStatement deleteValue;
-
- protected PreparedStatement renameNode;
-
/**
* Multidatabase JDBC Connection constructor.
*
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2010-05-26 13:39:19 UTC (rev 2437)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2010-05-26 14:31:13 UTC (rev 2438)
@@ -30,7 +30,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
@@ -61,76 +60,6 @@
+ " V.DATA, V.STORAGE_DESC from JCR_SITEM I LEFT OUTER JOIN JCR_SVALUE V ON (V.PROPERTY_ID=I.ID)"
+ " where I.I_CLASS=2 and I.CONTAINER_NAME=? and I.PARENT_ID=? order by I.NAME";
- protected PreparedStatement findItemById;
-
- protected PreparedStatement findItemByPath;
-
- protected PreparedStatement findItemByName;
-
- protected PreparedStatement findChildPropertyByPath;
-
- protected PreparedStatement findPropertyByName;
-
- protected PreparedStatement findDescendantNodes;
-
- protected PreparedStatement findDescendantProperties;
-
- protected PreparedStatement findReferences;
-
- protected PreparedStatement findValuesByPropertyId;
-
- protected PreparedStatement findValuesStorageDescriptorsByPropertyId;
-
- protected PreparedStatement findValuesDataByPropertyId;
-
- protected PreparedStatement findValueByPropertyIdOrderNumber;
-
- protected PreparedStatement findNodesByParentId;
-
- protected PreparedStatement findNodesByParentIdCQ;
-
- protected PreparedStatement findNodesCountByParentId;
-
- protected PreparedStatement findPropertiesByParentId;
-
- protected PreparedStatement findPropertiesByParentIdCQ;
-
- protected PreparedStatement findNodeMainPropertiesByParentIdentifierCQ;
-
- protected PreparedStatement findItemQPathByIdentifierCQ;
-
- protected PreparedStatement insertItem;
-
- protected PreparedStatement insertNode;
-
- protected PreparedStatement insertProperty;
-
- protected PreparedStatement insertReference;
-
- protected PreparedStatement insertValue;
-
- protected PreparedStatement updateItem;
-
- protected PreparedStatement updateItemPath;
-
- protected PreparedStatement updateNode;
-
- protected PreparedStatement updateProperty;
-
- protected PreparedStatement updateValue;
-
- protected PreparedStatement deleteItem;
-
- protected PreparedStatement deleteNode;
-
- protected PreparedStatement deleteProperty;
-
- protected PreparedStatement deleteReference;
-
- protected PreparedStatement deleteValue;
-
- protected PreparedStatement renameNode;
-
/**
* Singledatabase JDBC Connection constructor.
*
13 years, 11 months
exo-jcr SVN: r2437 - jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-05-26 09:39:19 -0400 (Wed, 26 May 2010)
New Revision: 2437
Modified:
jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientSessionImpl.java
Log:
EXOJCR-736: Problems with anonymous entrance on FTP and NPE
Modified: jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientSessionImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientSessionImpl.java 2010-05-26 13:26:50 UTC (rev 2436)
+++ jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientSessionImpl.java 2010-05-26 13:39:19 UTC (rev 2437)
@@ -417,6 +417,11 @@
ExoContainer container = ExoContainerContext.getCurrentContainer();
IdentityRegistry identityRegistry =
(IdentityRegistry)container.getComponentInstanceOfType(IdentityRegistry.class);
- identityRegistry.unregister(this.userId);
+
+ // The check need for case when login failed
+ if (this.userId != null)
+ {
+ identityRegistry.unregister(this.userId);
+ }
}
}
13 years, 11 months
exo-jcr SVN: r2436 - jcr/trunk/applications.
by do-not-reply@jboss.org
Author: dkatayev
Date: 2010-05-26 09:26:50 -0400 (Wed, 26 May 2010)
New Revision: 2436
Modified:
jcr/trunk/applications/Readme.txt
Log:
EXOJCR-739 Readme updated
Modified: jcr/trunk/applications/Readme.txt
===================================================================
--- jcr/trunk/applications/Readme.txt 2010-05-26 13:25:20 UTC (rev 2435)
+++ jcr/trunk/applications/Readme.txt 2010-05-26 13:26:50 UTC (rev 2436)
@@ -5,10 +5,9 @@
1.2. exo directory structure.
1.3. Maven version 2.2.1 (or higher).
1.4. Make sure you have run mvn instal within ./config folder.
-2. Go to folder "exo.jcr.applications.tomcat" and run "mvn clean install -P deploy" command.
+2. Go to folder "exo.jcr.applications.tomcat" and run "mvn clean install -P deploy" command.
2.1 If you want to deploy JBoss or Jonas use exo.jcr.applications.jboss or exo.jcr.applications.jonas respectively.
3. If the command has executed successfully, go to exo-tomcat and run "eXo run" command.
-4. You may use other product-exo-jcr-as* and an application server if you need.
Application server's specific configs is placed in product-patches/as/ folder.
13 years, 11 months