From e60d57ea42380a0b5f3fe453d06e0f8044fa3453 Mon Sep 17 00:00:00 2001 From: Samuel Langlois Date: Tue, 20 Aug 2013 17:17:31 +0000 Subject: [PATCH] Merged HEAD-QA to HEAD (4.2) (including moving test classes into separate folders) 51903 to 54309 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54310 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .classpath | 3 +- .../messages/portlets_nb_NO.properties | 2 +- .../alfresco/messages/webclient_de.properties | 2 +- .../messages/webclient_nb_NO.properties | 248 +- .../alfresco/messages/webclient_ru.properties | 20 +- .../web-client-application-context.xml | 20 +- .../web-client-config-workflow-actions.xml | 5 + config/alfresco/web-client-config.xml | 3 + pom.xml | 197 +- .../org/alfresco/web/app/Application.java | 19 +- .../org/alfresco/web/app/ContextListener.java | 52 +- .../alfresco/web/app/ContextListenerTest.java | 81 - .../web/app/servlet/AuthenticationFilter.java | 2 + .../web/app/servlet/AuthenticationHelper.java | 6 +- .../CmisSecurityContextCleanerFilter.java | 56 + .../org/alfresco/web/bean/BrowseBean.java | 2 + .../java/org/alfresco/web/bean/LoginBean.java | 7 +- .../web/bean/SpaceLinkDetailsDialog.java | 82 +- .../web/bean/TemplateMailHelperBean.java | 3 +- .../clipboard/WorkspaceClipboardItem.java | 2 +- .../bean/content/DocumentDetailsDialog.java | 66 +- .../content/DocumentLinkDetailsDialog.java | 62 +- .../web/bean/forums/ForumDetailsDialog.java | 82 +- .../web/bean/forums/ForumsDetailsDialog.java | 82 +- .../web/bean/forums/TopicDetailsDialog.java | 82 +- .../web/bean/preview/DocumentPreviewBean.java | 90 +- .../web/bean/preview/SpacePreviewBean.java | 110 +- .../alfresco/web/bean/repository/User.java | 505 ++-- .../web/bean/spaces/SpaceDetailsDialog.java | 86 +- .../alfresco/web/bean/wcm/AVMDetailsBean.java | 85 +- .../web/bean/wcm/WebSiteDetailsDialog.java | 82 +- .../bean/workflow/StartWorkflowWizard.java | 37 +- .../web/bean/workflow/WorkflowTaskNode.java | 16 + .../web/config/ClientConfigElement.java | 18 + .../web/config/ClientElementReader.java | 8 + .../web/forms/xforms/XFormsProcessor.java | 8 +- .../alfresco/web/ui/common/NodeListUtils.java | 100 + .../web/ui/common/NodePropertyComparator.java | 118 + .../org/alfresco/web/ui/repo/tag/PageTag.java | 772 +++--- .../web/app/ResourceBundleWrapperTest.java | 0 .../app/servlet/AuthenticationFilterTest.java | 81 + .../servlet/DefaultRemoteUserMapperTest.java | 0 .../web/config/WebClientConfigTest.java | 0 .../org/alfresco/web/forms/FormsTest.java | 0 .../org/alfresco/web/forms/XMLUtilTest.java | 0 .../web/forms/xforms/Schema2XFormsTest.java | 0 .../app/resourceBundleWrapperTest.properties | 0 .../CMIS-Core.xsd.template} | 0 .../CMIS-Messaging.xsd.template} | 2 +- .../CMISWS-Service.wsdl.template} | 22 +- .../web/WEB-INF/cmis11/CMIS-Core.xsd.template | 1396 ++++++++++ .../cmis11/CMIS-Messaging.xsd.template | 2309 +++++++++++++++++ .../cmis11/CMISWS-Service.wsdl.template | 1311 ++++++++++ source/web/WEB-INF/sun-jaxws.xml | 152 +- source/web/WEB-INF/web.xml | 112 +- source/web/WEB-INF/wsdl/xml.xsd | 55 - source/web/images/logo/hazelcast.png | Bin 0 -> 9834 bytes source/web/images/logo/hibernate_logo.gif | Bin 2728 -> 0 bytes source/web/images/logo/ibatis.png | Bin 0 -> 2139 bytes source/web/images/logo/java.gif | Bin 1289 -> 2790 bytes source/web/images/logo/libreoffice.png | Bin 0 -> 7630 bytes source/web/images/logo/mybatis.png | Bin 0 -> 8974 bytes source/web/images/logo/open-office.gif | Bin 1131 -> 0 bytes source/web/images/logo/solr.png | Bin 0 -> 21504 bytes source/web/jsp/dialog/about.jsp | 400 ++- .../workflow/pooled-tasks-todo-dashlet.jsp | 2 +- .../web/jsp/workflow/tasks-active-dashlet.jsp | 2 +- .../web/jsp/workflow/tasks-todo-dashlet.jsp | 4 +- .../scripts/ajax/tiny_mce_wcm_extensions.js | 5 +- .../themes/advanced/js/source_editor.js | 8 +- 70 files changed, 7094 insertions(+), 1988 deletions(-) delete mode 100644 source/java/org/alfresco/web/app/ContextListenerTest.java create mode 100644 source/java/org/alfresco/web/app/servlet/CmisSecurityContextCleanerFilter.java create mode 100644 source/java/org/alfresco/web/ui/common/NodeListUtils.java create mode 100644 source/java/org/alfresco/web/ui/common/NodePropertyComparator.java rename source/{java => test-java}/org/alfresco/web/app/ResourceBundleWrapperTest.java (100%) create mode 100644 source/test-java/org/alfresco/web/app/servlet/AuthenticationFilterTest.java rename source/{java => test-java}/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java (100%) rename source/{java => test-java}/org/alfresco/web/config/WebClientConfigTest.java (100%) rename source/{java => test-java}/org/alfresco/web/forms/FormsTest.java (100%) rename source/{java => test-java}/org/alfresco/web/forms/XMLUtilTest.java (100%) rename source/{java => test-java}/org/alfresco/web/forms/xforms/Schema2XFormsTest.java (100%) rename source/{java => test-resources}/org/alfresco/web/app/resourceBundleWrapperTest.properties (100%) rename source/web/WEB-INF/{wsdl/CMIS-Core.xsd => cmis10/CMIS-Core.xsd.template} (100%) rename source/web/WEB-INF/{wsdl/CMIS-Messaging.xsd => cmis10/CMIS-Messaging.xsd.template} (99%) rename source/web/WEB-INF/{wsdl/CMISWS-Service.wsdl => cmis10/CMISWS-Service.wsdl.template} (97%) create mode 100644 source/web/WEB-INF/cmis11/CMIS-Core.xsd.template create mode 100644 source/web/WEB-INF/cmis11/CMIS-Messaging.xsd.template create mode 100644 source/web/WEB-INF/cmis11/CMISWS-Service.wsdl.template delete mode 100644 source/web/WEB-INF/wsdl/xml.xsd create mode 100644 source/web/images/logo/hazelcast.png delete mode 100644 source/web/images/logo/hibernate_logo.gif create mode 100644 source/web/images/logo/ibatis.png create mode 100644 source/web/images/logo/libreoffice.png create mode 100644 source/web/images/logo/mybatis.png delete mode 100644 source/web/images/logo/open-office.gif create mode 100644 source/web/images/logo/solr.png diff --git a/.classpath b/.classpath index dcad915cad..0b2ff431b3 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + @@ -8,7 +9,7 @@ - + diff --git a/config/alfresco/messages/portlets_nb_NO.properties b/config/alfresco/messages/portlets_nb_NO.properties index 0370247320..29deb657f7 100755 --- a/config/alfresco/messages/portlets_nb_NO.properties +++ b/config/alfresco/messages/portlets_nb_NO.properties @@ -16,7 +16,7 @@ portlets.doclist.pdf_documents=PDF-dokumenter portlets.doclist.recently_modified=Nylig modifisert portlets.panel.description=Beskrivelse -portlets.panel.modified=Endret +portlets.panel.modified=Modifisert portlets.panel.modified_by=Modifisert av portlets.panel.created=Opprettet portlets.panel.created_by=Opprettet av: diff --git a/config/alfresco/messages/webclient_de.properties b/config/alfresco/messages/webclient_de.properties index 52db9441e5..ca01c21435 100644 --- a/config/alfresco/messages/webclient_de.properties +++ b/config/alfresco/messages/webclient_de.properties @@ -1738,7 +1738,7 @@ edit_properties=Eigenschaften des Inhalts bearbeiten save_changes=\u00c4nderungen speichern no_tasks=Keine Aufgaben gefunden. no_resources=Keine Ressourcen gefunden. -in_progress=l\u00e4uft +in_progress=in Bearbeitung by=von assignee=Bevollm\u00e4chtigter comment=Kommentar diff --git a/config/alfresco/messages/webclient_nb_NO.properties b/config/alfresco/messages/webclient_nb_NO.properties index b05d3644ca..8b5cbc2cc5 100755 --- a/config/alfresco/messages/webclient_nb_NO.properties +++ b/config/alfresco/messages/webclient_nb_NO.properties @@ -65,7 +65,7 @@ step3_edition_summary_desc=Tredje trinn, vis sammendrag av den nye utgaven step2_new_edition_summary_title=Andre trinn - Sammendrag step3_new_edition_summary_title=Tredje trinn - Sammendrag new_edition_summary_desc=Informasjonen du skrev inn, vises nedenfor. -new_edition_finish_instruction=Hvis du vil lukke denne veiviseren og bruke endringene, klikker du Avslutt. +new_edition_finish_instruction=Klikk p\u00e5 Fullf\u00f8rt for \u00e5 lukke denne veiviseren og bruke endringene dine. edition_properties=Egenskaper for utgave edition_notes=Utgavemerknader modify_translation_properties=Endre oversettelsesegenskapene n\u00e5r denne veiviseren er ferdig. @@ -90,9 +90,9 @@ view_versioned_properties=Egenskaper fra versjonsinnhold view_versioned_properties_description=Vis egenskapene for et versjonsinnhold. # Date Pattern -date_pattern=d. MMMM \u00e5\u00e5\u00e5\u00e5 -date_time_pattern=d. MMMM \u00e5\u00e5\u00e5\u00e5 kl. TT.mm -time_pattern=TT.mm +date_pattern=d MMMM yyyy +date_time_pattern=d MMMM yyyy HH:mm +time_pattern=HH:mm # General UI product_name=Alfresco @@ -150,7 +150,7 @@ offline_editing=Frakoblet redigering offline_title=Nedlasting av ''{0}'' for frakoblet redigering. # UI Component messages -done=Ferdig +done=Fullf\u00f8rt yes=Ja no=Nei error=Feil @@ -159,7 +159,7 @@ kilobyte=KB megabyte=MB gigabyte=GB locked_you=Element l\u00e5st av deg -locked_user=Element l\u00e5st av {0,choice,0#SHOULD_NOT_HAPPEN|1#user|1 +create_form_form_details_no_elements_in_schema=Dette skjemaet inneholder ikke noen elementdeklareringer. Et skjema m\u00e5 inneholde minst \u00e9n elementdeklarering for \u00e5 generere et skjema. +create_form_form_details_no_schema_selected= create_form_form_details_associated_web_projects=Dette skjemaet er for \u00f8yeblikket konfigurert for f\u00f8lgende Webprosjekter: create_form_configure_rendering_engine_templates_title=Konfigurer maler create_form_configure_rendering_engine_templates_step_title=Andre trinn \u2013 Konfigurer maler @@ -954,7 +954,7 @@ form_associated_with_form_instance_data_not_configured_for_web_project=Skjemaet run_action_title=Veiviser for kj\u00f8ring av handling run_action_desc=Denne veiviseren hjelper deg med \u00e5 kj\u00f8re en handling run_action_step1_title=F\u00f8rste trinn \u2013 Valgte handlinger -run_action_finish_instruction=Hvis du vil utf\u00f8re handlingen, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene dine, klikker du Tilbake. +run_action_finish_instruction=Hvis du vil utf\u00f8re handlingen, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene, klikker du Tilbake. create_rule_title=Veiviser for opprettelse av regel create_rule_desc=Denne veiviseren hjelper deg med \u00e5 opprette en ny regel. create_rule_step1_title=F\u00f8rste trinn \u2013 Velg vilk\u00e5r @@ -1061,7 +1061,7 @@ create_space_step2_title=Andre trinn \u2013 Alternativer for omr\u00e5de create_space_step2_desc=Velg alternativer for omr\u00e5de. create_space_step3_title=Tredje trinn \u2013 Detaljer for omr\u00e5de create_space_step3_desc=Skriv inn informasjon om omr\u00e5det. -create_space_finish_instruction=Hvis du vil lukke veiviseren og opprette omr\u00e5det, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom og endre valgene dine, klikker du Tilbake. +create_space_finish_instruction=Hvis du vil lukke veiviseren og opprette omr\u00e5det, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene, klikker du Tilbake. scratch=Kladd an_existing_space=Et eksisterende omr\u00e5de a_template=En mal @@ -1081,13 +1081,13 @@ existing_space=Eksisterende omr\u00e5de copy_existing_space=Kopier eksisterende omr\u00e5de structure=Struktur structure_contents=Struktur og innhold -space_copy_note=Merk: Eventuelle innholdsregler for omr\u00e5der kopieres ogs\u00e5. +space_copy_note=Merk: Eventuelle innholdsregler for plasser kopieres ogs\u00e5. space_type=Type omr\u00e5de space_type_create=Velg typen omr\u00e5de du vil opprette. container=Mappeomr\u00e5de container_desc=Et omr\u00e5de for oppbevaring og ordning av dokumenter og andre omr\u00e5der. forums_desc=Et omr\u00e5de for \u00e5 diskutere innhold med andre brukere. -space_type_note=Merk: Hvis du bare kan se \u00e9n type omr\u00e5de, er kanskje ikke andre typer omr\u00e5der aktivert. Se systemadministratoren for ytterligere hjelp. +space_type_note=Merk: Hvis du bare kan se \u00e9n type plass, er kanskje ikke andre typer plasser aktivert. Se systemadministratoren for ytterligere hjelp. template_space=Malomr\u00e5de select_template=Velg malen du vil bruke. @@ -1100,7 +1100,7 @@ create_website_step1_title=F\u00f8rste trinn \u2013 Detaljer for Webprosjekt create_website_step1_desc=Skriv inn informasjonen om Webprosjektet. website_dnsname=DNS-navn website_preview_provider=Forh\u00e5ndsvis leverand\u00f8r -validation_invalid_dns_name=Ugyldig DNS-navn for Webomr\u00e5de: kun alfanumeriske tegn og bindestrek, s\u00e5 lenge den ikke kommer f\u00f8rst eller sist, godtas (makslengde < 64). +validation_invalid_dns_name=Ugyldig DNS-navn for webomr\u00e5de: kun alfanumeriske tegn og bindestrek, s\u00e5 lenge den ikke kommer f\u00f8rst eller sist, godtas (makslengde <64). website_webapp=Standard Webapp website_createfrom=Opprett fra eksisterende Webprosjekt create_website_step2_title=Andre trinn \u2013 Opprett fra eksisterende Webprosjekt @@ -1148,12 +1148,12 @@ create_website_step6_desc=Velg brukere og rollene deres. website_notify=Send e-post til brukere create_website_step7_title=Sjuende trinn \u2013 Send e-post til brukere create_website_step7_desc=Varsle brukere av Webomr\u00e5det. -create_website_finish_instruction=Hvis du vil lukke veiviseren og opprette omr\u00e5det for Webprosjekt, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene dine, klikker du Tilbake. +create_website_finish_instruction=Hvis du vil lukke veiviseren og opprette omr\u00e5det for Webprosjekt, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene, klikker du Tilbake. create_website_summary_users=Brukere og roller server_already_exist=Server med navn {0} finnes allerede. edit_website_title=Veiviser for redigering av Webprosjekt edit_website_desc=Denne veiviseren hjelper deg med \u00e5 endre innstillingene for et omr\u00e5de for Webprosjekt. -edit_website_finish_instruction=Hvis du vil lukke denne veiviseren og lagre de endrede innstillingene for omr\u00e5det for Webprosjekt, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre innstillingene, klikker du Tilbake. +edit_website_finish_instruction=Hvis du vil lukke denne veiviseren og lagre de endrede innstillingene for omr\u00e5det for Webprosjekt, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene, klikker du Tilbake. edit_website=Rediger innstillinger for Webprosjekt workflow_settings=Innstillinger for arbeidsflyt workflow_not_configured=Arbeidsflyt ikke konfigurert @@ -1175,7 +1175,7 @@ invite_webusers_step1_title=F\u00f8rste trinn \u2013 Inviter brukere invite_webusers_step1_desc=Velg brukere og rollene deres. invite_webusers_step2_title=Andre trinn \u2013 Varsle brukere invite_webusers_step2_desc=Varsle de inviterte brukerne. -invite_webusers_finish_instruction=Hvis du vil lukke veiviseren og opprette brukersandkasser, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene dine, klikker du Tilbake. +invite_webusers_finish_instruction=Hvis du vil lukke veiviseren og opprette brukersandkasser, klikker du Fullf\u00f8r. Hvis du vil g\u00e5 gjennom eller endre valgene, klikker du Tilbake. # Delete Website Dialog messages delete_website=Slett Webprosjekt @@ -1221,14 +1221,14 @@ store_created_by=Opprettet av: store_working_users=Det {0,choice,0#er ingen brukere|1#er en bruker|1 - - - - - - - - - - org.alfresco.globalConfigTransactionalCache - - - 10 - + + - - + @@ -72,7 +59,6 @@ - diff --git a/config/alfresco/web-client-config-workflow-actions.xml b/config/alfresco/web-client-config-workflow-actions.xml index 57e3c952d4..065a6a30e9 100644 --- a/config/alfresco/web-client-config-workflow-actions.xml +++ b/config/alfresco/web-client-config-workflow-actions.xml @@ -371,4 +371,9 @@ + + + activiti$cloudWorkflow + + diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 71fc127d79..a1ae9748ef 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -49,6 +49,9 @@ 500 + + true + 500 diff --git a/pom.xml b/pom.xml index 2e0d90c842..42ef708778 100644 --- a/pom.xml +++ b/pom.xml @@ -8,14 +8,21 @@ org.alfresco alfresco-parent - 4.2.d-SNAPSHOT - ../../pom-experimental.xml + 4.2.0-QA-SNAPSHOT + ../../pom.xml alfresco war Alfresco Web Client Alfresco Web Client + + /alfresco + ${tomcat.default.alfresco.port} + webapp + ${project.build.directory}/patches + + ${project.groupId} @@ -53,6 +60,7 @@ ${project.groupId} alfresco-web-framework-commons ${project.version} + classes ${project.groupId} @@ -101,6 +109,10 @@ xml-apis xml-apis + + xerces + xerces + @@ -116,8 +128,17 @@ xml-apis xml-apis + + commons-digester + commons-digester + + + commons-logging + commons-logging + 1.1.1 + net.sf.chiba chiba @@ -148,15 +169,10 @@ standard 1.1.0 - - - ${project.groupId} - alfresco-web-framework-commons - ${project.version} - webapp - war - provided + org.apache.chemistry.opencmis + chemistry-opencmis-test-browser + ${dependency.opencmis.version} @@ -268,42 +284,143 @@ - maven-war-plugin - - - ${project.groupId} - alfresco-web-framework-commons - webapp - - WEB-INF/classes/* - - - - true - true + true + false + + + + ../../projects/remote-api/source/web + + WEB-INF/server-config.wsdd + + + + + + + pre-exploded-war + + exploded + + prepare-package + + + - - - enterprise - - - ${project.groupId} - alfresco-enterprise-repository - ${project.version} - - - ${project.groupId} - alfresco-enterprise-remote-api - ${project.version} - - - - + + solr-http + + + + maven-resources-plugin + + + copy-web-xml + process-resources + + copy-resources + + + ${project.build.patchesDirectory} + + + source/web + false + + WEB-INF/web.xml + + + + + + + + + + com.google.code.maven-replacer-plugin + replacer + + + disable-securecomms + process-resources + + replace + + + + + true + ${project.build.patchesDirectory}/WEB-INF/web.xml + + + ]]> + + + + ]]> + ]]> + + + + + + + maven-war-plugin + + + + ${project.build.patchesDirectory} + + + + + + + + + run + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + + + run-exploded-webapp + prepare-package + + run-war-only + + + + + + + + + + m2e + + + commons-logging + commons-logging + 1.1.1 + + runtime + + + mysql + mysql-connector-java + 5.1.14 + + + + diff --git a/source/java/org/alfresco/web/app/Application.java b/source/java/org/alfresco/web/app/Application.java index af6c4038af..ac0d76656e 100644 --- a/source/java/org/alfresco/web/app/Application.java +++ b/source/java/org/alfresco/web/app/Application.java @@ -391,25 +391,8 @@ public class Application { session.invalidate(); } - - // remove the username cookie value - Cookie authCookie = AuthenticationHelper.getAuthCookie(request); - if (authCookie != null) - { - HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); - if (response.isCommitted()) - { - // It's too late to do it now, but we can ask the login page to do it - request.getSession().setAttribute(AuthenticationHelper.SESSION_INVALIDATED, true); - } - else - { - authCookie.setMaxAge(0); - response.addCookie(authCookie); - } - } } - + // Explicitly invalidate the Alfresco ticket. This no longer happens on session expiry to allow for ticket // 'sharing' WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context); diff --git a/source/java/org/alfresco/web/app/ContextListener.java b/source/java/org/alfresco/web/app/ContextListener.java index 6bc4ea5a67..da1eb2e87a 100644 --- a/source/java/org/alfresco/web/app/ContextListener.java +++ b/source/java/org/alfresco/web/app/ContextListener.java @@ -53,8 +53,6 @@ public class ContextListener implements ServletContextListener, HttpSessionListe private static Log logger = LogFactory.getLog(ContextListener.class); private ServletContext servletContext; - private ServletContextListener enterpriseListener; - private String enterpriseListenerClass = "org.alfresco.enterprise.repo.EnterpriseContextListener"; /** * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) @@ -124,51 +122,15 @@ public class ContextListener implements ServletContextListener, HttpSessionListe } catch (Exception ex) {} } - synchronized(this) - { - findEnterpriseListener(); - if (enterpriseListener != null) - { - // Perform any extra context initialisation required for enterprise. - enterpriseListener.contextInitialized(event); - } - } } - protected void findEnterpriseListener() - { - try - { - Class c = Class.forName(enterpriseListenerClass); - enterpriseListener = (ServletContextListener) c.newInstance(); - } - catch (ClassNotFoundException e) - { - // It's OK not to have the enterprise context destroyer available. - } - catch (InstantiationException e) - { - logger.error("Failed to instantiate enterprise ServletContextListener.", e); - } - catch (IllegalAccessException e) - { - logger.error("Failed to instantiate enterprise ServletContextListener.", e); - } - } /** * {@inheritDoc} */ public void contextDestroyed(ServletContextEvent event) { - synchronized(this) - { - if (enterpriseListener != null) - { - // Perform any extra destruction required for enterprise. - enterpriseListener.contextDestroyed(event); - } - } + // NOOP } /** @@ -188,16 +150,4 @@ public class ContextListener implements ServletContextListener, HttpSessionListe if (logger.isDebugEnabled()) logger.debug("HTTP session destroyed: " + event.getSession().getId()); } - - /** - * Inject a different class name (from the default) for the enterprise ServletContextListener. - *

- * Useful for testing. - * - * @param listenerClass Class name to use. - */ - protected void setEnterpriseListenerClass(String listenerClass) - { - this.enterpriseListenerClass = listenerClass; - } } diff --git a/source/java/org/alfresco/web/app/ContextListenerTest.java b/source/java/org/alfresco/web/app/ContextListenerTest.java deleted file mode 100644 index bc06ac112b..0000000000 --- a/source/java/org/alfresco/web/app/ContextListenerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2012 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.web.app; - -import static org.junit.Assert.*; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -/** - * Tests for the ContextListener class. - * - * @author Matt Ward - */ -@RunWith(MockitoJUnitRunner.class) -public class ContextListenerTest -{ - private ContextListener contextListener; - private @Mock ServletContextEvent event; - - - @Before - public void setUp() throws Exception - { - contextListener = new ContextListener(); - contextListener.setEnterpriseListenerClass("org.alfresco.web.app.ContextListenerTest$StubEnterpriseListener"); - StubEnterpriseListener.enterpriseDestroyed = false; - } - - @Test - public void testContextDestroyed() - { - contextListener.findEnterpriseListener(); - contextListener.contextDestroyed(event); - - assertTrue("Enterprise contextDestroyed() not executed.", StubEnterpriseListener.enterpriseDestroyed); - } - - - /** - * ServletContextListener to simulate an enterprise-specific context listener. - */ - protected static class StubEnterpriseListener implements ServletContextListener - { - static boolean enterpriseDestroyed; - - @Override - public void contextDestroyed(ServletContextEvent arg0) - { - enterpriseDestroyed = true; - } - - @Override - public void contextInitialized(ServletContextEvent arg0) - { - // Noop - } - } -} diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java index 4bc60b1d29..e88781abbf 100644 --- a/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java +++ b/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.extensions.config.ConfigService; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter; import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.alfresco.web.config.ClientConfigElement; @@ -114,6 +115,7 @@ public class AuthenticationFilter extends AbstractLifecycleBean implements Depen { // continue filter chaining chain.doFilter(req, res); + AuthenticationUtil.clearCurrentSecurityContext(); } } } diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java index 4f629fc467..b1051c4f40 100644 --- a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java +++ b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java @@ -39,10 +39,10 @@ import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.webdav.auth.RemoteUserMapper; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.web.app.Application; import org.alfresco.web.app.portlet.AlfrescoFacesPortlet; @@ -85,6 +85,7 @@ public final class AuthenticationHelper private static final String REMOTE_USER_MAPPER = "RemoteUserMapper"; private static final String UNPROTECTED_AUTH_SERVICE = "authenticationService"; private static final String PERSON_SERVICE = "personService"; + private static final String AUTHORITY_SERVICE = "AuthorityService"; /** cookie names */ private static final String COOKIE_ALFUSER = "alfUser0"; @@ -604,8 +605,9 @@ public final class AuthenticationHelper // If the remote user mapper is configured, we may be able to map in an externally authenticated user if (userId != null) { + AuthorityService authorityService = (AuthorityService) wc.getBean(AUTHORITY_SERVICE); // We have a previously-cached user with the wrong identity - replace them - if (user != null && !user.getUserName().equals(userId)) + if (user != null && !authorityService.isGuestAuthority(user.getUserName()) && !user.getUserName().equals(userId)) { if (logger.isDebugEnabled()) logger.debug("We have a previously-cached user with the wrong identity - replace them"); diff --git a/source/java/org/alfresco/web/app/servlet/CmisSecurityContextCleanerFilter.java b/source/java/org/alfresco/web/app/servlet/CmisSecurityContextCleanerFilter.java new file mode 100644 index 0000000000..8f814d02be --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/CmisSecurityContextCleanerFilter.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.web.app.servlet; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import net.sf.acegisecurity.context.ContextHolder; + +/** + * Clears security context. It should follow Authentication filters in the chain and should be mapped for CMIS requests only + * + * @author Dmitry Velichkevich + * @since 4.1.5 + */ +public class CmisSecurityContextCleanerFilter implements Filter +{ + @Override + public void destroy() + { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException + { + ContextHolder.setContext(null); + chain.doFilter(servletRequest, servletResponse); + } + + @Override + public void init(FilterConfig config) throws ServletException + { + } +} diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index 0060afa903..d1208ca193 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -1093,6 +1093,8 @@ public class BrowseBean implements IContextListener, Serializable sp.setLimit(searchLimit); } + sp.setBulkFetchEnabled(Application.getClientConfig(FacesContext.getCurrentInstance()).isBulkFetchEnabled()); + results = this.getSearchService().query(sp); if (logger.isDebugEnabled()) logger.debug("Search results returned: " + results.length()); diff --git a/source/java/org/alfresco/web/bean/LoginBean.java b/source/java/org/alfresco/web/bean/LoginBean.java index 61a9a79c51..fa6efb3c2b 100644 --- a/source/java/org/alfresco/web/bean/LoginBean.java +++ b/source/java/org/alfresco/web/bean/LoginBean.java @@ -30,6 +30,8 @@ import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.faces.validator.ValidatorException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationDisallowedException; @@ -379,6 +381,9 @@ public class LoginBean implements Serializable // the app to continue without redirecting to the login page Application.setCurrentUser(fc, user); + // Save the current username to cookie + AuthenticationHelper.setUsernameCookie((HttpServletRequest) fc.getExternalContext().getRequest(),(HttpServletResponse) fc.getExternalContext().getResponse(), this.username); + // Programatically retrieve the LoginOutcomeBean from JSF LoginOutcomeBean loginOutcomeBean = (LoginOutcomeBean) fc.getApplication().createValueBinding( "#{LoginOutcomeBean}").getValue(fc); @@ -388,7 +393,7 @@ public class LoginBean implements Serializable String redirectURL = loginOutcomeBean.getRedirectURL(); // ALF-10312: Validate we are redirecting within this web app - if (redirectURL != null && !redirectURL.startsWith(fc.getExternalContext().getRequestContextPath())) + if (redirectURL != null && !redirectURL.isEmpty() && !redirectURL.startsWith(fc.getExternalContext().getRequestContextPath())) { if (logger.isWarnEnabled()) logger.warn("Security violation. Unable to redirect to external location: " + redirectURL); diff --git a/source/java/org/alfresco/web/bean/SpaceLinkDetailsDialog.java b/source/java/org/alfresco/web/bean/SpaceLinkDetailsDialog.java index f0446b539a..a3c67e4eb3 100644 --- a/source/java/org/alfresco/web/bean/SpaceLinkDetailsDialog.java +++ b/source/java/org/alfresco/web/bean/SpaceLinkDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,6 +18,7 @@ */ package org.alfresco.web.bean; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,6 +34,8 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.component.UIActionLink; public class SpaceLinkDetailsDialog extends BaseDetailsBean implements NavigationSupport @@ -106,7 +109,6 @@ public class SpaceLinkDetailsDialog extends BaseDetailsBean implements Navigatio public void nextItem(ActionEvent event) { - boolean foundNextItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -114,41 +116,16 @@ public class SpaceLinkDetailsDialog extends BaseDetailsBean implements Navigatio { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -159,7 +136,6 @@ public class SpaceLinkDetailsDialog extends BaseDetailsBean implements Navigatio public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -167,38 +143,16 @@ public class SpaceLinkDetailsDialog extends BaseDetailsBean implements Navigatio { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/TemplateMailHelperBean.java b/source/java/org/alfresco/web/bean/TemplateMailHelperBean.java index e6b99efd5b..690ffb5438 100644 --- a/source/java/org/alfresco/web/bean/TemplateMailHelperBean.java +++ b/source/java/org/alfresco/web/bean/TemplateMailHelperBean.java @@ -28,6 +28,7 @@ import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.executer.MailActionExecuter; import org.alfresco.repo.template.I18NMessageMethod; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ContentReader; @@ -168,7 +169,7 @@ public class TemplateMailHelperBean implements Serializable MimeMessageHelper message = new MimeMessageHelper(mimeMessage); message.setTo(to); message.setSubject(subject); - message.setText(finalBody); + message.setText(finalBody, MailActionExecuter.isHTML(finalBody)); message.setFrom(from); } }; diff --git a/source/java/org/alfresco/web/bean/clipboard/WorkspaceClipboardItem.java b/source/java/org/alfresco/web/bean/clipboard/WorkspaceClipboardItem.java index 66404d1e37..e65c1e14f6 100644 --- a/source/java/org/alfresco/web/bean/clipboard/WorkspaceClipboardItem.java +++ b/source/java/org/alfresco/web/bean/clipboard/WorkspaceClipboardItem.java @@ -136,7 +136,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem public boolean paste(final FacesContext fc, String viewId, final int action) { final ServiceRegistry serviceRegistry = getServiceRegistry(); - final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper(); + final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper(); if (super.canCopyToViewId(viewId) || WORKSPACE_PASTE_VIEW_ID.equals(viewId) || FORUMS_PASTE_VIEW_ID.equals(viewId) || FORUM_PASTE_VIEW_ID.equals(viewId)) { diff --git a/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java b/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java index 7965fdab17..ea88e1cf5d 100644 --- a/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java +++ b/source/java/org/alfresco/web/bean/content/DocumentDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -22,6 +22,7 @@ import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -59,6 +60,8 @@ import org.alfresco.web.bean.ml.SingleEditionBean; import org.alfresco.web.bean.repository.MapNode; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodePropertyComparator; +import org.alfresco.web.ui.common.NodeListUtils; import org.alfresco.web.ui.common.ReportedException; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils.URLMode; @@ -711,32 +714,12 @@ public class DocumentDetailsDialog extends BaseDetailsBean implements Navigatio List nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i=0; i nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // see above - for (int i=0; i nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i=0; i nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // see above - for (int i=0; i params = link.getParameterMap(); String id = params.get("id"); @@ -131,41 +133,16 @@ public class ForumDetailsDialog extends BaseDetailsBean implements NavigationSup { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -176,7 +153,6 @@ public class ForumDetailsDialog extends BaseDetailsBean implements NavigationSup public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -184,38 +160,16 @@ public class ForumDetailsDialog extends BaseDetailsBean implements NavigationSup { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/forums/ForumsDetailsDialog.java b/source/java/org/alfresco/web/bean/forums/ForumsDetailsDialog.java index 7ac15e60db..08bf237d3b 100644 --- a/source/java/org/alfresco/web/bean/forums/ForumsDetailsDialog.java +++ b/source/java/org/alfresco/web/bean/forums/ForumsDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,6 +18,7 @@ */ package org.alfresco.web.bean.forums; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,6 +35,8 @@ import org.alfresco.web.bean.BaseDetailsBean; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.component.UIActionLink; public class ForumsDetailsDialog extends BaseDetailsBean implements NavigationSupport @@ -123,7 +126,6 @@ public class ForumsDetailsDialog extends BaseDetailsBean implements NavigationSu public void nextItem(ActionEvent event) { - boolean foundNextItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -131,41 +133,16 @@ public class ForumsDetailsDialog extends BaseDetailsBean implements NavigationSu { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -176,7 +153,6 @@ public class ForumsDetailsDialog extends BaseDetailsBean implements NavigationSu public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -184,38 +160,16 @@ public class ForumsDetailsDialog extends BaseDetailsBean implements NavigationSu { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/forums/TopicDetailsDialog.java b/source/java/org/alfresco/web/bean/forums/TopicDetailsDialog.java index eb9f46d49a..36b16a6710 100644 --- a/source/java/org/alfresco/web/bean/forums/TopicDetailsDialog.java +++ b/source/java/org/alfresco/web/bean/forums/TopicDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,6 +18,7 @@ */ package org.alfresco.web.bean.forums; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,6 +35,8 @@ import org.alfresco.web.bean.BaseDetailsBean; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.component.UIActionLink; public class TopicDetailsDialog extends BaseDetailsBean implements NavigationSupport @@ -123,7 +126,6 @@ public class TopicDetailsDialog extends BaseDetailsBean implements NavigationSup public void nextItem(ActionEvent event) { - boolean foundNextItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -131,41 +133,16 @@ public class TopicDetailsDialog extends BaseDetailsBean implements NavigationSup { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -176,7 +153,6 @@ public class TopicDetailsDialog extends BaseDetailsBean implements NavigationSup public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -184,38 +160,16 @@ public class TopicDetailsDialog extends BaseDetailsBean implements NavigationSup { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/preview/DocumentPreviewBean.java b/source/java/org/alfresco/web/bean/preview/DocumentPreviewBean.java index f4800d5a14..37c438bd2f 100644 --- a/source/java/org/alfresco/web/bean/preview/DocumentPreviewBean.java +++ b/source/java/org/alfresco/web/bean/preview/DocumentPreviewBean.java @@ -1,23 +1,24 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.web.bean.preview; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,8 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.component.UIActionLink; /** @@ -100,31 +103,11 @@ public class DocumentPreviewBean extends BasePreviewBean implements NavigationSu List nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupContentAction(next.getId(), false); - break; - } - } + String currentSortColumn = this.browseBean.getContentRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getContentRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + Node next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupContentAction(next.getId(), false); } } } @@ -139,28 +122,11 @@ public class DocumentPreviewBean extends BasePreviewBean implements NavigationSu List nodes = this.browseBean.getContent(); if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // prepare for showing details for this node - this.browseBean.setupContentAction(previous.getId(), false); - break; - } - } + String currentSortColumn = this.browseBean.getContentRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getContentRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + Node previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupContentAction(previous.getId(), false); } } } diff --git a/source/java/org/alfresco/web/bean/preview/SpacePreviewBean.java b/source/java/org/alfresco/web/bean/preview/SpacePreviewBean.java index fa77c6c48d..42398c51c4 100644 --- a/source/java/org/alfresco/web/bean/preview/SpacePreviewBean.java +++ b/source/java/org/alfresco/web/bean/preview/SpacePreviewBean.java @@ -1,23 +1,24 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.web.bean.preview; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,8 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.component.UIActionLink; /** @@ -89,7 +92,6 @@ public class SpacePreviewBean extends BasePreviewBean implements NavigationSuppo public void nextItem(ActionEvent event) { - boolean foundNextItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -97,41 +99,16 @@ public class SpacePreviewBean extends BasePreviewBean implements NavigationSuppo { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -142,7 +119,6 @@ public class SpacePreviewBean extends BasePreviewBean implements NavigationSuppo public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -150,38 +126,16 @@ public class SpacePreviewBean extends BasePreviewBean implements NavigationSuppo { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/repository/User.java b/source/java/org/alfresco/web/bean/repository/User.java index efe59b3d2e..fcdb9332be 100644 --- a/source/java/org/alfresco/web/bean/repository/User.java +++ b/source/java/org/alfresco/web/bean/repository/User.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2005-2010 Alfresco Software Limited. * * This file is part of Alfresco @@ -14,184 +14,184 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.web.bean.repository; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import javax.faces.context.FacesContext; + * along with Alfresco. If not, see . + */ +package org.alfresco.web.bean.repository; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; import javax.servlet.ServletContext; - -import org.alfresco.model.ApplicationModel; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.SessionUser; -import org.alfresco.repo.configuration.ConfigurableService; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; + +import org.alfresco.model.ApplicationModel; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.SessionUser; +import org.alfresco.repo.configuration.ConfigurableService; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.jsf.FacesContextUtils; - -/** - * Bean that represents the currently logged in user - * - * @author gavinc - */ -public final class User implements SessionUser -{ - private static final long serialVersionUID = -90577901805847829L; - - private String companyRootId; - private String homeSpaceId; - private String userName; - private String ticket; - private NodeRef person; - private String fullName = null; - private Boolean administrator = null; - - private Preferences preferences = null; - - /** - * Constructor - * - * @param userName constructor for the user - */ - public User(String userName, String ticket, NodeRef person) - { - if (userName == null || ticket == null || person == null) - { - throw new IllegalArgumentException("All user details are mandatory!"); - } - - this.userName = userName; - this.ticket = ticket; - this.person = person; - } - - /** - * Forces a clear of any cached or calcluated values - */ - public void reset() - { - this.fullName = null; - this.administrator = null; - this.preferences = null; - } - - /** - * @return The user name - */ - public String getUserName() - { - return this.userName; - } - - /** - * Return the full name of the Person this User represents - * - * @param service NodeService to use - * - * @return The full name - */ - public String getFullName(NodeService service) - { - if (this.fullName == null) - { - String firstName = (String)service.getProperty(this.person, ContentModel.PROP_FIRSTNAME); - String lastName = (String)service.getProperty(this.person, ContentModel.PROP_LASTNAME); - this.fullName = (firstName != null ? firstName : "") + ' ' + (lastName != null ? lastName : ""); - } - - return this.fullName; - } - - /** - * @return Retrieves the user's home space (this may be the id of the company home space) - */ - public String getHomeSpaceId() - { - return this.homeSpaceId; - } - - /** - * @param homeSpaceId Sets the id of the users home space - */ - public void setHomeSpaceId(String homeSpaceId) - { - this.homeSpaceId = homeSpaceId; - } - - /** - * @return Retrieves the company home space - */ - public String getCompanyRootId() - { - return this.companyRootId; - } - - /** - * @param companyRootId Sets the id of the company home space - */ - public void setCompanyRootId(String companyRootId) - { - this.companyRootId = companyRootId; - } - - /** - * @return Returns the ticket. - */ - public String getTicket() - { - return this.ticket; - } - - /** - * @return Returns the person NodeRef - */ - public NodeRef getPerson() - { - return this.person; - } - - /** - * @return If the current user has Admin Authority - */ - public boolean isAdmin() - { - if (administrator == null) - { - administrator = Repository.getServiceRegistry(FacesContext.getCurrentInstance()) - .getAuthorityService().hasAdminAuthority(); - } - - return administrator; - } - - /** - * @return The Preferences for the User - */ + +/** + * Bean that represents the currently logged in user + * + * @author gavinc + */ +public final class User implements SessionUser +{ + private static final long serialVersionUID = -90577901805847829L; + + private String companyRootId; + private String homeSpaceId; + private String userName; + private String ticket; + private NodeRef person; + private String fullName = null; + private Boolean administrator = null; + + private Preferences preferences = null; + + /** + * Constructor + * + * @param userName constructor for the user + */ + public User(String userName, String ticket, NodeRef person) + { + if (userName == null || ticket == null || person == null) + { + throw new IllegalArgumentException("All user details are mandatory!"); + } + + this.userName = userName; + this.ticket = ticket; + this.person = person; + } + + /** + * Forces a clear of any cached or calcluated values + */ + public void reset() + { + this.fullName = null; + this.administrator = null; + this.preferences = null; + } + + /** + * @return The user name + */ + public String getUserName() + { + return this.userName; + } + + /** + * Return the full name of the Person this User represents + * + * @param service NodeService to use + * + * @return The full name + */ + public String getFullName(NodeService service) + { + if (this.fullName == null) + { + String firstName = (String)service.getProperty(this.person, ContentModel.PROP_FIRSTNAME); + String lastName = (String)service.getProperty(this.person, ContentModel.PROP_LASTNAME); + this.fullName = (firstName != null ? firstName : "") + ' ' + (lastName != null ? lastName : ""); + } + + return this.fullName; + } + + /** + * @return Retrieves the user's home space (this may be the id of the company home space) + */ + public String getHomeSpaceId() + { + return this.homeSpaceId; + } + + /** + * @param homeSpaceId Sets the id of the users home space + */ + public void setHomeSpaceId(String homeSpaceId) + { + this.homeSpaceId = homeSpaceId; + } + + /** + * @return Retrieves the company home space + */ + public String getCompanyRootId() + { + return this.companyRootId; + } + + /** + * @param companyRootId Sets the id of the company home space + */ + public void setCompanyRootId(String companyRootId) + { + this.companyRootId = companyRootId; + } + + /** + * @return Returns the ticket. + */ + public String getTicket() + { + return this.ticket; + } + + /** + * @return Returns the person NodeRef + */ + public NodeRef getPerson() + { + return this.person; + } + + /** + * @return If the current user has Admin Authority + */ + public boolean isAdmin() + { + if (administrator == null) + { + administrator = Repository.getServiceRegistry(FacesContext.getCurrentInstance()) + .getAuthorityService().hasAdminAuthority(); + } + + return administrator; + } + + /** + * @return The Preferences for the User + */ Preferences getPreferences(FacesContext fc) - { - if (this.preferences == null) - { + { + if (this.preferences == null) + { this.preferences = new Preferences(getUserPreferencesRef( FacesContextUtils.getRequiredWebApplicationContext(fc))); - } - return this.preferences; - } - - /** + } + return this.preferences; + } + + /** * @return The Preferences for the User */ Preferences getPreferences(ServletContext sc) @@ -205,88 +205,87 @@ public final class User implements SessionUser } /** - * Get or create the node used to store user preferences. - * Utilises the 'configurable' aspect on the Person linked to this user. - */ + * Get or create the node used to store user preferences. + * Utilises the 'configurable' aspect on the Person linked to this user. + */ synchronized NodeRef getUserPreferencesRef(WebApplicationContext context) - { - final ServiceRegistry registry = (ServiceRegistry) context.getBean("ServiceRegistry"); - final NodeService nodeService = registry.getNodeService(); - final SearchService searchService = registry.getSearchService(); - final NamespaceService namespaceService = registry.getNamespaceService(); - final TransactionService txService = registry.getTransactionService(); - final ConfigurableService configurableService = (ConfigurableService) context.getBean("ConfigurableService"); - RetryingTransactionHelper txnHelper = registry.getRetryingTransactionHelper(); - return txnHelper.doInTransaction(new RetryingTransactionCallback() - { - - public NodeRef execute() throws Throwable - { - NodeRef prefRef = null; - NodeRef person = getPerson(); - if (nodeService.hasAspect(person, ApplicationModel.ASPECT_CONFIGURABLE) == false) - { - // if the repository is in read-only mode just return null - if (txService.isReadOnly()) - { - return null; - } - else - { - // create the configuration folder for this Person node - configurableService.makeConfigurable(person); - } - } - - // target of the assoc is the configurations folder ref - NodeRef configRef = configurableService.getConfigurationFolder(person); - if (configRef == null) - { - throw new IllegalStateException("Unable to find associated 'configurations' folder for node: " - + person); - } - - String xpath = NamespaceService.APP_MODEL_PREFIX + ":" + "preferences"; - List nodes = searchService.selectNodes(configRef, xpath, null, namespaceService, false); - - if (nodes.size() == 1) - { - prefRef = nodes.get(0); - } - else - { - // create the preferences Node for this user (if repo is not read-only) - if (txService.isReadOnly() == false) + { + final ServiceRegistry registry = (ServiceRegistry) context.getBean("ServiceRegistry"); + final NodeService nodeService = registry.getNodeService(); + final SearchService searchService = registry.getSearchService(); + final NamespaceService namespaceService = registry.getNamespaceService(); + final TransactionService txService = registry.getTransactionService(); + final ConfigurableService configurableService = (ConfigurableService) context.getBean("ConfigurableService"); + RetryingTransactionHelper txnHelper = registry.getTransactionService().getRetryingTransactionHelper(); + return txnHelper.doInTransaction(new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + NodeRef prefRef = null; + NodeRef person = getPerson(); + if (nodeService.hasAspect(person, ApplicationModel.ASPECT_CONFIGURABLE) == false) + { + // if the repository is in read-only mode just return null + if (txService.isReadOnly()) { - ChildAssociationRef childRef = nodeService.createNode(configRef, - ContentModel.ASSOC_CONTAINS, QName.createQName( - NamespaceService.APP_MODEL_1_0_URI, "preferences"), - ContentModel.TYPE_CMOBJECT); - - prefRef = childRef.getChildRef(); - } - } - return prefRef; - } - }); - } - - /** - * Returns the full name of the user represented by the given NodeRef - * - * @param nodeService The node service instance - * @param user The user to get the full name for - * @return The full name - */ - public static String getFullName(NodeService nodeService, NodeRef user) - { - Map props = nodeService.getProperties(user); - String firstName = (String)props.get(ContentModel.PROP_FIRSTNAME); - String lastName = (String)props.get(ContentModel.PROP_LASTNAME); - String fullName = firstName + ((lastName != null && lastName.length() > 0) ? " " + lastName : ""); - - return fullName; - } + return null; + } + else + { + // create the configuration folder for this Person node + configurableService.makeConfigurable(person); + } + } + + // target of the assoc is the configurations folder ref + NodeRef configRef = configurableService.getConfigurationFolder(person); + if (configRef == null) + { + throw new IllegalStateException("Unable to find associated 'configurations' folder for node: " + + person); + } + + String xpath = NamespaceService.APP_MODEL_PREFIX + ":" + "preferences"; + List nodes = searchService.selectNodes(configRef, xpath, null, namespaceService, false); + + if (nodes.size() == 1) + { + prefRef = nodes.get(0); + } + else + { + // create the preferences Node for this user (if repo is not read-only) + if (txService.isReadOnly() == false) + { + ChildAssociationRef childRef = nodeService.createNode(configRef, + ContentModel.ASSOC_CONTAINS, QName.createQName( + NamespaceService.APP_MODEL_1_0_URI, "preferences"), + ContentModel.TYPE_CMOBJECT); + + prefRef = childRef.getChildRef(); + } + } + return prefRef; + } + }); + } + + /** + * Returns the full name of the user represented by the given NodeRef + * + * @param nodeService The node service instance + * @param user The user to get the full name for + * @return The full name + */ + public static String getFullName(NodeService nodeService, NodeRef user) + { + Map props = nodeService.getProperties(user); + String firstName = (String)props.get(ContentModel.PROP_FIRSTNAME); + String lastName = (String)props.get(ContentModel.PROP_LASTNAME); + String fullName = firstName + ((lastName != null && lastName.length() > 0) ? " " + lastName : ""); + + return fullName; + } /** * Returns the full name of the user plus their userid in the form [id] @@ -313,4 +312,4 @@ public final class User implements SessionUser return nameAndId.toString(); } -} +} diff --git a/source/java/org/alfresco/web/bean/spaces/SpaceDetailsDialog.java b/source/java/org/alfresco/web/bean/spaces/SpaceDetailsDialog.java index ebefde152d..f3bcb41049 100644 --- a/source/java/org/alfresco/web/bean/spaces/SpaceDetailsDialog.java +++ b/source/java/org/alfresco/web/bean/spaces/SpaceDetailsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -20,6 +20,7 @@ package org.alfresco.web.bean.spaces; import java.text.MessageFormat; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,6 +40,8 @@ import org.alfresco.web.bean.TemplateSupportBean; import org.alfresco.web.bean.dialog.NavigationSupport; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.NodeListUtils; +import org.alfresco.web.ui.common.NodePropertyComparator; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils.URLMode; import org.alfresco.web.ui.common.component.UIActionLink; @@ -165,49 +168,23 @@ public class SpaceDetailsDialog extends BaseDetailsBean implements NavigationSup */ public void nextItem(ActionEvent event) { - boolean foundNextItem = false; UIActionLink link = (UIActionLink)event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); if (id != null && id.length() != 0) { - NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); + NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i=0; i params = link.getParameterMap(); String id = params.get("id"); if (id != null && id.length() != 0) { - NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); + NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i=0; i nodes = getNodes(); if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the item has changed etc. - for (int i=0; i nodes = getNodes(); if (nodes.size() > 1) { - // see above - for (int i=0; i params = link.getParameterMap(); String id = params.get("id"); @@ -123,41 +125,16 @@ public class WebSiteDetailsDialog extends BaseDetailsBean implements NavigationS { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node next = null; if (nodes.size() > 1) { - // perform a linear search - this is slow but stateless - // otherwise we would have to manage state of last selected node - // this gets very tricky as this bean is instantiated once and never - // reset - it does not know when the document has changed etc. - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node next; - // found our item - navigate to next - if (i != nodes.size() - 1) - { - next = nodes.get(i + 1); - } - else - { - // handle wrapping case - next = nodes.get(0); - } - - // prepare for showing details for this node - this.browseBean.setupSpaceAction(next.getId(), false); - - // we found a next item - foundNextItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + next = NodeListUtils.nextItem(nodes, id); + this.browseBean.setupSpaceAction(next.getId(), false); } - - // if we did not find a next item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundNextItem == false) + if (next == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); @@ -168,7 +145,6 @@ public class WebSiteDetailsDialog extends BaseDetailsBean implements NavigationS public void previousItem(ActionEvent event) { - boolean foundPreviousItem = false; UIActionLink link = (UIActionLink) event.getComponent(); Map params = link.getParameterMap(); String id = params.get("id"); @@ -176,38 +152,16 @@ public class WebSiteDetailsDialog extends BaseDetailsBean implements NavigationS { NodeRef currNodeRef = new NodeRef(Repository.getStoreRef(), id); List nodes = this.browseBean.getParentNodes(currNodeRef); + Node previous = null; if (nodes.size() > 1) { - // see above - for (int i = 0; i < nodes.size(); i++) - { - if (id.equals(nodes.get(i).getId()) == true) - { - Node previous; - // found our item - navigate to previous - if (i != 0) - { - previous = nodes.get(i - 1); - } - else - { - // handle wrapping case - previous = nodes.get(nodes.size() - 1); - } - - // show details for this node - this.browseBean.setupSpaceAction(previous.getId(), false); - - // we found a next item - foundPreviousItem = true; - } - } + String currentSortColumn = this.browseBean.getSpacesRichList().getCurrentSortColumn(); + boolean currentSortDescending = this.browseBean.getSpacesRichList().isCurrentSortDescending(); + Collections.sort(nodes, new NodePropertyComparator(currentSortColumn, !currentSortDescending)); + previous = NodeListUtils.previousItem(nodes, id); + this.browseBean.setupSpaceAction(previous.getId(), false); } - - // if we did not find a previous item make sure the current node is - // in the dispatch context otherwise the details screen will go back - // to the default one. - if (foundPreviousItem == false) + if (previous == null) { Node currNode = new Node(currNodeRef); this.navigator.setupDispatchContext(currNode); diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java index fc49485618..389cbcb1a3 100644 --- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java +++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java @@ -34,7 +34,6 @@ import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; import javax.transaction.UserTransaction; -import org.springframework.extensions.config.ConfigElement; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.repo.publishing.PublishingEventHelper; @@ -68,6 +67,7 @@ import org.alfresco.web.ui.common.component.UIActionLink; import org.alfresco.web.ui.common.component.data.UIRichList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.config.ConfigElement; /** * Bean implementation for the Start Workflow Wizard. @@ -85,6 +85,7 @@ public class StartWorkflowWizard extends BaseWizardBean transient private Map workflows; protected List wcmWorkflows; + protected List excludedWorkflows; protected List invitationWorkflows; protected List publishingWorkflows; @@ -574,6 +575,7 @@ public class StartWorkflowWizard extends BaseWizardBean List configuredWcmWorkflows = this.getWCMWorkflowNames(); List configuredInvitationWorkflows = this.getInvitationServiceWorkflowNames(); List publishingWorkflows = this.getPublishingWorkflowNames(); + List excludedWorkflows = this.getExcludedWorkflows(); List workflowDefs = this.getWorkflowService().getDefinitions(); for (WorkflowDefinition workflowDef : workflowDefs) @@ -582,7 +584,8 @@ public class StartWorkflowWizard extends BaseWizardBean if (configuredWcmWorkflows.contains(name) == false && configuredInvitationWorkflows.contains(name) == false && - publishingWorkflows.contains(name) == false) + publishingWorkflows.contains(name) == false && + excludedWorkflows.contains(name) == false) { // add the workflow if it is not a WCM specific workflow String label = workflowDef.title; @@ -789,6 +792,36 @@ public class StartWorkflowWizard extends BaseWizardBean return wcmWorkflows; } + + /** + * Get the Names of globally excluded workflow-names. + * + * @return The names of the workflows to exclude. + */ + protected List getExcludedWorkflows() + { + if ((excludedWorkflows == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) + { + FacesContext fc = FacesContext.getCurrentInstance(); + ConfigElement config = Application.getConfigService(fc).getGlobalConfig().getConfigElement("excluded-workflows"); + if (config != null) + { + StringTokenizer t = new StringTokenizer(config.getValue().trim(), ", "); + excludedWorkflows = new ArrayList(t.countTokens()); + while (t.hasMoreTokens()) + { + String wfName = t.nextToken(); + excludedWorkflows.add(wfName); + } + } + else + { + excludedWorkflows = Collections.emptyList(); + } + } + return excludedWorkflows; + } + /** * Get the Names of the Invitation Service Workflows * diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowTaskNode.java b/source/java/org/alfresco/web/bean/workflow/WorkflowTaskNode.java index 19c4d5862e..bb9ecf895a 100644 --- a/source/java/org/alfresco/web/bean/workflow/WorkflowTaskNode.java +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowTaskNode.java @@ -11,6 +11,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTransition; import org.alfresco.service.namespace.QName; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.TransientMapNode; +import org.springframework.extensions.surf.util.I18NUtil; /** * Wrapper around a {@link WorkflowTask} to allow it to be approached as a {@link Node}. @@ -68,6 +69,16 @@ public class WorkflowTaskNode extends TransientMapNode { // add the task itself as a property propertyWrapper.put("workflowTask", workflowTask); } + + // Add an additional property, containing a human-friendly representation of the priority + Integer priority = (Integer) workflowTask.getProperties().get(WorkflowModel.PROP_PRIORITY); + String priorityMessage = ""; + if (priority != null) + { + priorityMessage = I18NUtil.getMessage(getPriorityMessageKey(priority), I18NUtil.getLocale()); + } + propertyWrapper.put("priorityMessage", priorityMessage); + } @Override @@ -112,4 +123,9 @@ public class WorkflowTaskNode extends TransientMapNode { return super.put(QName.resolveToQNameString(WorkflowTaskNode.this.getNamespacePrefixResolver(), key.toString()), value); } } + + protected String getPriorityMessageKey(int priority) + { + return "listconstraint.bpm_allowedPriority." + priority; + } } diff --git a/source/java/org/alfresco/web/config/ClientConfigElement.java b/source/java/org/alfresco/web/config/ClientConfigElement.java index 0ede9af8b8..7d123329e8 100644 --- a/source/java/org/alfresco/web/config/ClientConfigElement.java +++ b/source/java/org/alfresco/web/config/ClientConfigElement.java @@ -86,6 +86,7 @@ public class ClientConfigElement extends ConfigElementAdapter private int pickerSearchMinimum = 2; private boolean checkContextAgainstPath = false; private boolean allowUserScriptExecute = false; + private boolean isBulkFetchEnabled = true; /** @@ -963,4 +964,21 @@ public class ClientConfigElement extends ConfigElementAdapter { this.allowUserScriptExecute = allowUserScriptExecute; } + + /** + * @return true if bulk fetch is enabled + */ + public boolean isBulkFetchEnabled() + { + return isBulkFetchEnabled; + } + + /** + * @param isBulkFetchEnabled + */ + /*package*/ void setBulkFetchEnabled(boolean isBulkFetchEnabled) + { + this.isBulkFetchEnabled = isBulkFetchEnabled; + } + } diff --git a/source/java/org/alfresco/web/config/ClientElementReader.java b/source/java/org/alfresco/web/config/ClientElementReader.java index 36743b668c..bc5e21d7cc 100644 --- a/source/java/org/alfresco/web/config/ClientElementReader.java +++ b/source/java/org/alfresco/web/config/ClientElementReader.java @@ -43,6 +43,7 @@ public class ClientElementReader implements ConfigElementReader public static final String ELEMENT_SEARCHMINIMUM = "search-minimum"; public static final String ELEMENT_SEARCHANDTERMS = "search-and-terms"; public static final String ELEMENT_SEARCHMAXRESULTS = "search-max-results"; + public static final String ELEMENT_BULKFETCHENABLED = "bulk-fetch-enabled"; public static final String ELEMENT_SELECTORSSEARCHMAXRESULTS = "selectors-search-max-results"; public static final String ELEMENT_INVITESEARCHMAXRESULTS = "invite-users-max-results"; public static final String ELEMENT_TASKSCOMPLETEDMAXRESULTS = "tasks-completed-max-results"; @@ -141,6 +142,13 @@ public class ClientElementReader implements ConfigElementReader configElement.setSearchMaxResults(Integer.parseInt(searchMaxResults.getTextTrim())); } + // get the search max results size + Element isBulkFetchEnabled = element.element(ELEMENT_BULKFETCHENABLED); + if (isBulkFetchEnabled != null) + { + configElement.setBulkFetchEnabled(Boolean.parseBoolean(isBulkFetchEnabled.getTextTrim())); + } + // get the selectors search max results size Element selectorsSearchMaxResults = element.element(ELEMENT_SELECTORSSEARCHMAXRESULTS); if (selectorsSearchMaxResults != null) diff --git a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java index 3f2bffd79a..2a1790f29c 100644 --- a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java +++ b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java @@ -426,8 +426,12 @@ public class XFormsProcessor implements FormProcessor { return result; } - throw new RuntimeException("widget definitions " + this + - " and " + other + " collide"); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("widget definitions " + this + " and " + other + " may collide"); + } + return 0; } public String toString() diff --git a/source/java/org/alfresco/web/ui/common/NodeListUtils.java b/source/java/org/alfresco/web/ui/common/NodeListUtils.java new file mode 100644 index 0000000000..f9e2f814e3 --- /dev/null +++ b/source/java/org/alfresco/web/ui/common/NodeListUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.web.ui.common; + +import java.util.List; + +import org.alfresco.web.bean.repository.Node; + +/** + * Helper class to get next or previos node from the list of nodes. +* +* @author vdanilchenko +* @since 4.1.3 +*/ +public class NodeListUtils +{ + /** + * @param nodes the list of the nodes + * @param currentNodeId the current node ID + */ + public static Node nextItem(List nodes, String currentNodeId) + { + Node next = null; + + // perform a linear search - this is slow but stateless + // otherwise we would have to manage state of last selected node + // this gets very tricky as this bean is instantiated once and never + // reset - it does not know when the document has changed etc. + for (int i=0; i nodes, String currentNodeId) + { + Node previous = null; + + // perform a linear search - this is slow but stateless + // otherwise we would have to manage state of last selected node + // this gets very tricky as this bean is instantiated once and never + // reset - it does not know when the document has changed etc. + for (int i=0; i. + */ +package org.alfresco.web.ui.common; + +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.web.bean.repository.DataDictionary; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.app.Application; + +import org.springframework.web.jsf.FacesContextUtils; + +import java.util.Comparator; +import java.util.Date; +import java.util.Map; + +import javax.faces.context.FacesContext; + +/** + * Comparator to sort the list of nodes according theirs properties and sort order + * + * @author vdanilchenko + * @since 4.1.3 + */ +public class NodePropertyComparator implements Comparator +{ + private String propertyName; + private boolean isAscending; + private DataDictionary dataDictionary; + + /** + * @param propertyName the property name to sort + * @param isAscending sort order + */ + public NodePropertyComparator(String propertyName, boolean isAscending) + { + super(); + this.propertyName = propertyName; + this.isAscending = isAscending; + + FacesContext context = FacesContext.getCurrentInstance(); + dataDictionary = (DataDictionary)FacesContextUtils.getRequiredWebApplicationContext(context).getBean(Application.BEAN_DATA_DICTIONARY); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public int compare(Object node1, Object node2) + { + Map nodeProperties1 = ((Node)node1).getProperties(); + Map nodeProperties2 = ((Node)node2).getProperties(); + PropertyDefinition pd1 = dataDictionary.getPropertyDefinition((Node)node1, propertyName); + PropertyDefinition pd2 = dataDictionary.getPropertyDefinition((Node)node2, propertyName); + Comparable propertyValue1, propertyValue2; + if((pd1 != null) && (pd2 != null)) + { + String typeName = pd1.getDataType().getName().getLocalName(); + + if(typeName.equals("datetime")) + { + propertyValue1 = (Date) nodeProperties1.get(propertyName); + propertyValue2 = (Date) nodeProperties2.get(propertyName); + } + else if(typeName.equals("long")) + { + propertyValue1 = (Long) nodeProperties1.get(propertyName); + propertyValue2 = (Long) nodeProperties2.get(propertyName); + } + else if(typeName.equals("boolean")) + { + propertyValue1 = (Boolean) nodeProperties1.get(propertyName); + propertyValue2 = (Boolean) nodeProperties2.get(propertyName); + } + //string types: text, mltext + //non comparable types: locale, content + else + { + propertyValue1 = nodeProperties1.get(propertyName).toString(); + propertyValue2 = nodeProperties2.get(propertyName).toString(); + } + } + //additional properties doesn't contains in the node properties + //their type can't be resolved using DataDictionary + //QNameNodeMap resolves them on first invocation and puts them into the map of node properties + else + { + if(propertyName.equals("size")) + { + propertyValue1 = (Long) nodeProperties1.get(propertyName); + propertyValue2 = (Long) nodeProperties2.get(propertyName); + } + else + { + propertyValue1 = nodeProperties1.get(propertyName).toString(); + propertyValue2 = nodeProperties2.get(propertyName).toString(); + } + } + + if(isAscending) + { + return propertyValue1.compareTo(propertyValue2); + } + return propertyValue2.compareTo(propertyValue1); + } +} diff --git a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java index 24cdd141c9..1396aedff7 100644 --- a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java +++ b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java @@ -1,392 +1,380 @@ -/* - * Copyright (C) 2005-2013 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -/* - * There is an Enterprise overlay for this file - */ - -package org.alfresco.web.ui.repo.tag; - -import java.io.IOException; -import java.io.Writer; - -import javax.faces.context.FacesContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.tagext.TagSupport; - -import org.alfresco.web.app.Application; -import org.alfresco.web.app.servlet.FacesHelper; -import org.alfresco.web.bean.coci.CCProperties; -import org.alfresco.web.config.ClientConfigElement; -import org.alfresco.web.ui.common.Utils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * A non-JSF tag library that adds the HTML begin and end tags if running in servlet mode - * - * @author gavinc - */ -public class PageTag extends TagSupport -{ - private static final long serialVersionUID = 8142765393181557228L; - - private final static String SCRIPTS_START = "\n"; - private final static String STYLES_START = "\n"; - - private final static String[] SCRIPTS = - { - // menu javascript - "/scripts/menu.js", - // webdav javascript - "/scripts/webdav.js", - // base yahoo file - "/scripts/ajax/yahoo/yahoo/yahoo-min.js", - // io handling (AJAX) - "/scripts/ajax/yahoo/connection/connection-min.js", - // event handling - "/scripts/ajax/yahoo/event/event-min.js", - // mootools - "/scripts/ajax/mootools.v1.11.js", - // common Alfresco util methods - "/scripts/ajax/common.js", - // pop-up panel helper objects - "/scripts/ajax/summary-info.js", - // ajax pickers - "/scripts/ajax/picker.js", - "/scripts/ajax/tagger.js", - // validation handling - "/scripts/validation.js" - }; - - private final static String[] CSS = - { - "/css/main.css", - "/css/picker.css" - }; - -/** - * Please ensure you understand the terms of the license before changing the contents of this file. - */ - - private final static String ALF_LOGO_HTTP = "http://www.alfresco.com/assets/images/logos/community-4.2.png"; - private final static String ALF_LOGO_HTTPS = "https://www.alfresco.com/assets/images/logos/community-4.2.png"; - private final static String ALF_URL = "http://www.alfresco.com"; - private final static String ALF_TEXT = "Alfresco Community"; - private final static String ALF_COPY = "Supplied free of charge with " + - "no support, " + - "no certification, " + - "no maintenance, " + - "no warranty and " + - "no indemnity by " + - "Alfresco or its " + - "Certified Partners. " + - "Click here for support. " + - "Alfresco Software Inc. © 2005-2013 All rights reserved."; - - private final static Log logger = LogFactory.getLog(PageTag.class); - private static String alfresco = null; - private static String loginPage = null; - - private long startTime = 0; - private String title; - private String titleId; - private String doctypeRootElement; - private String doctypePublic; - private String doctypeSystem; - - /** - * @return The title for the page - */ - public String getTitle() - { - return title; - } - - /** - * @param title Sets the page title - */ - public void setTitle(String title) - { - this.title = title; - } - - /** - * @return The title message Id for the page - */ - public String getTitleId() - { - return titleId; - } - - /** - * @param titleId Sets the page title message Id - */ - public void setTitleId(String titleId) - { - this.titleId = titleId; - } - - public String getDoctypeRootElement() - { - return this.doctypeRootElement; - } - - public void setDoctypeRootElement(final String doctypeRootElement) - { - this.doctypeRootElement = doctypeRootElement; - } - - public String getDoctypePublic() - { - return this.doctypePublic; - } - - public void setDoctypePublic(final String doctypePublic) - { - this.doctypePublic = doctypePublic; - } - - public String getDoctypeSystem() - { - return this.doctypeSystem; - } - - public void setDoctypeSystem(final String doctypeSystem) - { - this.doctypeSystem = doctypeSystem; - } - - public void release() - { - super.release(); - this.title = null; - this.titleId = null; - this.doctypeRootElement = null; - this.doctypeSystem = null; - this.doctypePublic = null; - } - - /** - * @see javax.servlet.jsp.tagext.TagSupport#doStartTag() - */ - public int doStartTag() throws JspException - { - if (logger.isDebugEnabled()) - startTime = System.currentTimeMillis(); - - try - { - String reqPath = ((HttpServletRequest)pageContext.getRequest()).getContextPath(); - Writer out = pageContext.getOut(); - - if (!Application.inPortalServer()) - { - if (this.getDoctypeRootElement() != null && - this.getDoctypePublic() != null) - { - out.write("\n"); - } - else - { - out.write("\n"); - } - out.write(""); - out.write("\n"); - out.write(""); - if (this.titleId != null && this.titleId.length() != 0) - { - out.write(Utils.encode(Application.getMessage(pageContext.getSession(), this.titleId))); - } - else if (this.title != null && this.title.length() != 0) - { - out.write(Utils.encode(this.title)); - } - else - { - out.write("Alfresco Web Client"); - } - out.write("\n"); - out.write("\n"); - out.write("\n"); - } - - // CSS style includes - for (final String css : PageTag.CSS) - { - out.write(STYLES_START); - out.write(reqPath); - out.write(css); - out.write(STYLES_MAIN); - } - - // JavaScript includes - for (final String s : PageTag.SCRIPTS) - { - out.write(SCRIPTS_START); - out.write(reqPath); - out.write(s); - out.write(SCRIPTS_END); - } - - out.write("\n"); // end - generate naked javascript code - - if (!Application.inPortalServer()) - { - out.write(""); - out.write("\n"); - } - } - catch (IOException ioe) - { - throw new JspException(ioe.toString()); - } - - return EVAL_BODY_INCLUDE; - } - - /** - * @see javax.servlet.jsp.tagext.TagSupport#doEndTag() - */ - public int doEndTag() throws JspException - { - try - { - HttpServletRequest req = (HttpServletRequest)pageContext.getRequest(); - if (req.getRequestURI().endsWith(getLoginPage()) == false) - { - pageContext.getOut().write(getAlfrescoButton()); - } - - if (!Application.inPortalServer()) - { - pageContext.getOut().write("\n"); - } - } - catch (IOException ioe) - { - throw new JspException(ioe.toString()); - } - - if (logger.isDebugEnabled()) - { - long endTime = System.currentTimeMillis(); - logger.debug("Time to generate page: " + (endTime - startTime) + "ms"); - } - - return super.doEndTag(); - } - - private String getLoginPage() - { - if (PageTag.loginPage == null) - { - PageTag.loginPage = Application.getLoginPage(pageContext.getServletContext()); - } - - return PageTag.loginPage; - } - -/** - * Please ensure you understand the terms of the license before changing the contents of this file. - */ - - private String getAlfrescoButton() - { - if (PageTag.alfresco == null) - { - final HttpServletRequest req = (HttpServletRequest)pageContext.getRequest(); - PageTag.alfresco = ("
" + - "" + - "" +"" + - "" + ALF_COPY + - "
"); - } - return PageTag.alfresco; - } - - /** - * This method generate code for setting window.onload reference as - * we need to open WebDav or CIFS URL in a new window. - * - * Executes via javascript code(function onloadFunc()) in "onload.js" include file. - * - * @return Returns window.onload javascript code - */ - private static void generateWindowOnloadCode(Writer out) - throws IOException - { - FacesContext fc = FacesContext.getCurrentInstance(); - if (fc != null) - { - CCProperties ccProps = (CCProperties)FacesHelper.getManagedBean(fc, "CCProperties"); - if (ccProps.getWebdavUrl() != null || ccProps.getCifsPath() != null) - { - out.write("window.onload=function(){onloadFunc(\""); - if (ccProps.getWebdavUrl() != null) - { - out.write(ccProps.getWebdavUrl()); - } - out.write("\",\""); - if (ccProps.getCifsPath() != null) - { - String val = ccProps.getCifsPath(); - val = Utils.replace(val, "\\", "\\\\"); // encode escape character - out.write(val); - } - out.write("\");};"); - - // reset session bean state - ccProps.setCifsPath(null); - ccProps.setWebdavUrl(null); - } - } - } -} +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/* Enterprise overlay */ + +package org.alfresco.web.ui.repo.tag; + +import java.io.IOException; +import java.io.Writer; + +import javax.faces.context.FacesContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.TagSupport; + +import org.alfresco.web.app.Application; +import org.alfresco.web.app.servlet.FacesHelper; +import org.alfresco.web.bean.coci.CCProperties; +import org.alfresco.web.config.ClientConfigElement; +import org.alfresco.web.ui.common.Utils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A non-JSF tag library that adds the HTML begin and end tags if running in servlet mode + * + * @author gavinc + */ +public class PageTag extends TagSupport +{ + private static final long serialVersionUID = 8142765393181557228L; + + private final static String SCRIPTS_START = "\n"; + private final static String STYLES_START = "\n"; + + private final static String[] SCRIPTS = + { + // menu javascript + "/scripts/menu.js", + // webdav javascript + "/scripts/webdav.js", + // base yahoo file + "/scripts/ajax/yahoo/yahoo/yahoo-min.js", + // io handling (AJAX) + "/scripts/ajax/yahoo/connection/connection-min.js", + // event handling + "/scripts/ajax/yahoo/event/event-min.js", + // mootools + "/scripts/ajax/mootools.v1.11.js", + // common Alfresco util methods + "/scripts/ajax/common.js", + // pop-up panel helper objects + "/scripts/ajax/summary-info.js", + // ajax pickers + "/scripts/ajax/picker.js", + "/scripts/ajax/tagger.js", + // validation handling + "/scripts/validation.js" + }; + + private final static String[] CSS = + { + "/css/main.css", + "/css/picker.css" + }; + +/** + * Please ensure you understand the terms of the license before changing the contents of this file. + */ + + private final static String ALF_URL = "http://www.alfresco.com"; + private final static String ALF_LOGO = "/images/logo/alfresco_enterprise.gif"; + private final static String ALF_TEXT = "Alfresco Enterprise"; + private final static String ALF_COPY = "Certified and supported. Alfresco Software Inc. © 2005-2013 All rights reserved."; + + private final static Log logger = LogFactory.getLog(PageTag.class); + private static String alfresco = null; + private static String loginPage = null; + + private long startTime = 0; + private String title; + private String titleId; + private String doctypeRootElement; + private String doctypePublic; + private String doctypeSystem; + + /** + * @return The title for the page + */ + public String getTitle() + { + return title; + } + + /** + * @param title Sets the page title + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return The title message Id for the page + */ + public String getTitleId() + { + return titleId; + } + + /** + * @param titleId Sets the page title message Id + */ + public void setTitleId(String titleId) + { + this.titleId = titleId; + } + + public String getDoctypeRootElement() + { + return this.doctypeRootElement; + } + + public void setDoctypeRootElement(final String doctypeRootElement) + { + this.doctypeRootElement = doctypeRootElement; + } + + public String getDoctypePublic() + { + return this.doctypePublic; + } + + public void setDoctypePublic(final String doctypePublic) + { + this.doctypePublic = doctypePublic; + } + + public String getDoctypeSystem() + { + return this.doctypeSystem; + } + + public void setDoctypeSystem(final String doctypeSystem) + { + this.doctypeSystem = doctypeSystem; + } + + public void release() + { + super.release(); + this.title = null; + this.titleId = null; + this.doctypeRootElement = null; + this.doctypeSystem = null; + this.doctypePublic = null; + } + + /** + * @see javax.servlet.jsp.tagext.TagSupport#doStartTag() + */ + public int doStartTag() throws JspException + { + if (logger.isDebugEnabled()) + startTime = System.currentTimeMillis(); + + try + { + String reqPath = ((HttpServletRequest)pageContext.getRequest()).getContextPath(); + Writer out = pageContext.getOut(); + + if (!Application.inPortalServer()) + { + if (this.getDoctypeRootElement() != null && + this.getDoctypePublic() != null) + { + out.write("\n"); + } + else + { + out.write("\n"); + } + out.write(""); + out.write("\n"); + out.write(""); + if (this.titleId != null && this.titleId.length() != 0) + { + out.write(Utils.encode(Application.getMessage(pageContext.getSession(), this.titleId))); + } + else if (this.title != null && this.title.length() != 0) + { + out.write(Utils.encode(this.title)); + } + else + { + out.write("Alfresco Web Client"); + } + out.write("\n"); + out.write("\n"); + out.write("\n"); + } + + // CSS style includes + for (final String css : PageTag.CSS) + { + out.write(STYLES_START); + out.write(reqPath); + out.write(css); + out.write(STYLES_MAIN); + } + + // JavaScript includes + for (final String s : PageTag.SCRIPTS) + { + out.write(SCRIPTS_START); + out.write(reqPath); + out.write(s); + out.write(SCRIPTS_END); + } + + out.write("\n"); // end - generate naked javascript code + + if (!Application.inPortalServer()) + { + out.write(""); + out.write("\n"); + } + } + catch (IOException ioe) + { + throw new JspException(ioe.toString()); + } + + return EVAL_BODY_INCLUDE; + } + + /** + * @see javax.servlet.jsp.tagext.TagSupport#doEndTag() + */ + public int doEndTag() throws JspException + { + try + { + HttpServletRequest req = (HttpServletRequest)pageContext.getRequest(); + if (req.getRequestURI().endsWith(getLoginPage()) == false) + { + pageContext.getOut().write(getAlfrescoButton()); + } + + if (!Application.inPortalServer()) + { + pageContext.getOut().write("\n"); + } + } + catch (IOException ioe) + { + throw new JspException(ioe.toString()); + } + + if (logger.isDebugEnabled()) + { + long endTime = System.currentTimeMillis(); + logger.debug("Time to generate page: " + (endTime - startTime) + "ms"); + } + + return super.doEndTag(); + } + + private String getLoginPage() + { + if (PageTag.loginPage == null) + { + PageTag.loginPage = Application.getLoginPage(pageContext.getServletContext()); + } + + return PageTag.loginPage; + } + +/** + * Please ensure you understand the terms of the license before changing the contents of this file. + */ + + private String getAlfrescoButton() + { + if (PageTag.alfresco == null) + { + final String reqPath = ((HttpServletRequest)pageContext.getRequest()).getContextPath(); + PageTag.alfresco = ("
" + + "" + + "" + + "" + + "" + ALF_COPY + + "
"); + } + return PageTag.alfresco; + } + + /** + * This method generate code for setting window.onload reference as + * we need to open WebDav or CIFS URL in a new window. + * + * Executes via javascript code(function onloadFunc()) in "onload.js" include file. + * + * @return Returns window.onload javascript code + */ + private static void generateWindowOnloadCode(Writer out) + throws IOException + { + FacesContext fc = FacesContext.getCurrentInstance(); + if (fc != null) + { + CCProperties ccProps = (CCProperties)FacesHelper.getManagedBean(fc, "CCProperties"); + if (ccProps.getWebdavUrl() != null || ccProps.getCifsPath() != null) + { + out.write("window.onload=function(){onloadFunc(\""); + if (ccProps.getWebdavUrl() != null) + { + out.write(ccProps.getWebdavUrl()); + } + out.write("\",\""); + if (ccProps.getCifsPath() != null) + { + String val = ccProps.getCifsPath(); + val = Utils.replace(val, "\\", "\\\\"); // encode escape character + out.write(val); + } + out.write("\");};"); + + // reset session bean state + ccProps.setCifsPath(null); + ccProps.setWebdavUrl(null); + } + } + } +} diff --git a/source/java/org/alfresco/web/app/ResourceBundleWrapperTest.java b/source/test-java/org/alfresco/web/app/ResourceBundleWrapperTest.java similarity index 100% rename from source/java/org/alfresco/web/app/ResourceBundleWrapperTest.java rename to source/test-java/org/alfresco/web/app/ResourceBundleWrapperTest.java diff --git a/source/test-java/org/alfresco/web/app/servlet/AuthenticationFilterTest.java b/source/test-java/org/alfresco/web/app/servlet/AuthenticationFilterTest.java new file mode 100644 index 0000000000..017eebb144 --- /dev/null +++ b/source/test-java/org/alfresco/web/app/servlet/AuthenticationFilterTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.web.app.servlet; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +import javax.servlet.FilterChain; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.alfresco.repo.tenant.TenantContextHolder; +import org.alfresco.web.config.ClientConfigElement; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.config.ConfigImpl; +import org.springframework.extensions.config.ConfigService; + +/** + * Test for the AuthenticationFilter class. + * + * @author alex.mukha + */ +@RunWith(MockitoJUnitRunner.class) +public class AuthenticationFilterTest +{ + private static String loginPage = "loginpage"; + + private String tenantDomain = "tenantDomain-" + System.currentTimeMillis(); + + private @Mock ServletContext context; + private @Mock HttpServletResponse res; + private @Mock FilterChain chain; + private @Mock ApplicationEvent event; + + /** + * Test for the fix for ALF-18611 + * @throws Exception + */ + @Test + public void testALF18611() throws Exception + { + ClientConfigElement clientConfigElementMock = mock(ClientConfigElement.class); + when(clientConfigElementMock.getLoginPage()).thenReturn(loginPage); + ConfigImpl configImplMock = mock(ConfigImpl.class); + when(configImplMock.getConfigElement(ClientConfigElement.CONFIG_ELEMENT_ID)).thenReturn(clientConfigElementMock); + ConfigService configServiceMock = mock(ConfigService.class); + when(configServiceMock.getGlobalConfig()).thenReturn(configImplMock); + + TenantContextHolder.setTenantDomain(tenantDomain); + assertTrue("Tenant domain should be equal", TenantContextHolder.getTenantDomain().equals(tenantDomain.toLowerCase())); + AuthenticationFilter authenticationFilter = new AuthenticationFilter(); + authenticationFilter.setConfigService(configServiceMock); + authenticationFilter.onBootstrap(event); + + HttpServletRequest reqMock = mock(HttpServletRequest.class); + when(reqMock.getRequestURI()).thenReturn(loginPage); + authenticationFilter.doFilter(context, reqMock, res, chain); + + assertTrue("Tenant domain should be empty", TenantContextHolder.getTenantDomain() == null); + } +} diff --git a/source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java b/source/test-java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java similarity index 100% rename from source/java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java rename to source/test-java/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java diff --git a/source/java/org/alfresco/web/config/WebClientConfigTest.java b/source/test-java/org/alfresco/web/config/WebClientConfigTest.java similarity index 100% rename from source/java/org/alfresco/web/config/WebClientConfigTest.java rename to source/test-java/org/alfresco/web/config/WebClientConfigTest.java diff --git a/source/java/org/alfresco/web/forms/FormsTest.java b/source/test-java/org/alfresco/web/forms/FormsTest.java similarity index 100% rename from source/java/org/alfresco/web/forms/FormsTest.java rename to source/test-java/org/alfresco/web/forms/FormsTest.java diff --git a/source/java/org/alfresco/web/forms/XMLUtilTest.java b/source/test-java/org/alfresco/web/forms/XMLUtilTest.java similarity index 100% rename from source/java/org/alfresco/web/forms/XMLUtilTest.java rename to source/test-java/org/alfresco/web/forms/XMLUtilTest.java diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java b/source/test-java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java similarity index 100% rename from source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java rename to source/test-java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java diff --git a/source/java/org/alfresco/web/app/resourceBundleWrapperTest.properties b/source/test-resources/org/alfresco/web/app/resourceBundleWrapperTest.properties similarity index 100% rename from source/java/org/alfresco/web/app/resourceBundleWrapperTest.properties rename to source/test-resources/org/alfresco/web/app/resourceBundleWrapperTest.properties diff --git a/source/web/WEB-INF/wsdl/CMIS-Core.xsd b/source/web/WEB-INF/cmis10/CMIS-Core.xsd.template similarity index 100% rename from source/web/WEB-INF/wsdl/CMIS-Core.xsd rename to source/web/WEB-INF/cmis10/CMIS-Core.xsd.template diff --git a/source/web/WEB-INF/wsdl/CMIS-Messaging.xsd b/source/web/WEB-INF/cmis10/CMIS-Messaging.xsd.template similarity index 99% rename from source/web/WEB-INF/wsdl/CMIS-Messaging.xsd rename to source/web/WEB-INF/cmis10/CMIS-Messaging.xsd.template index a6ad7878c6..b889164c3e 100644 --- a/source/web/WEB-INF/wsdl/CMIS-Messaging.xsd +++ b/source/web/WEB-INF/cmis10/CMIS-Messaging.xsd.template @@ -22,7 +22,7 @@ jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1" elementFormDefault="qualified"> - diff --git a/source/web/WEB-INF/wsdl/CMISWS-Service.wsdl b/source/web/WEB-INF/cmis10/CMISWS-Service.wsdl.template similarity index 97% rename from source/web/WEB-INF/wsdl/CMISWS-Service.wsdl rename to source/web/WEB-INF/cmis10/CMISWS-Service.wsdl.template index b749511e81..913cdf04c5 100644 --- a/source/web/WEB-INF/wsdl/CMISWS-Service.wsdl +++ b/source/web/WEB-INF/cmis10/CMISWS-Service.wsdl.template @@ -22,9 +22,9 @@ - - @@ -1121,52 +1121,52 @@ + location="<%cmisbase%>/DiscoveryService" /> + location="<%cmisbase%>/MultiFilingService" /> + location="<%cmisbase%>/NavigationService" /> - + - + + location="<%cmisbase%>/RelationshipService" /> + location="<%cmisbase%>/RepositoryService" /> + location="<%cmisbase%>/VersioningService" /> - + diff --git a/source/web/WEB-INF/cmis11/CMIS-Core.xsd.template b/source/web/WEB-INF/cmis11/CMIS-Core.xsd.template new file mode 100644 index 0000000000..44ad01f06a --- /dev/null +++ b/source/web/WEB-INF/cmis11/CMIS-Core.xsd.template @@ -0,0 +1,1396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is the property definition id for this + property instance. This is not required to be set when used + as a default value. This is required to be set when used for + query result set or returning properties on an object. + + + + + + + This is the localname as defined by the property + definition. + + + + + + + This is the displayname as defined by the property + definition. + + + + + + + This is the queryName. This must be specified if + this is the result of a query. If aliases are used, the alias is to + be specified here instead of the queryName. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is the id for the parent type definition. + If this is a base type, this is MUST NOT be present. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + If set, this field holds the principal who is + used for anonymous access. This principal can then be + passed to the ACL services to specify what permissions + anonymous users should have. + + + + + + + + If set, this field holds the principal who is + used for everyone's access. This principal can then be + passed to the ACL services to specify what permissions + everyone should have. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Multiple entries are OR'ed together. Any + permission that specified is sufficient to + provide rights required in key + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This user can be used on setting ACLs to specify + the permission this + user context should have. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is the root tag for a CMIS AllowableActions + Document Type + + + + + + + + This is the root tag for a CMIS Query Document Type + + + + + + + This is the root tag for a CMIS ACL Document Type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/web/WEB-INF/cmis11/CMIS-Messaging.xsd.template b/source/web/WEB-INF/cmis11/CMIS-Messaging.xsd.template new file mode 100644 index 0000000000..f73091597b --- /dev/null +++ b/source/web/WEB-INF/cmis11/CMIS-Messaging.xsd.template @@ -0,0 +1,2309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an extension element to hold any + repository or + vendor-specific extensions + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/web/WEB-INF/cmis11/CMISWS-Service.wsdl.template b/source/web/WEB-INF/cmis11/CMISWS-Service.wsdl.template new file mode 100644 index 0000000000..9d049a3f41 --- /dev/null +++ b/source/web/WEB-INF/cmis11/CMISWS-Service.wsdl.template @@ -0,0 +1,1311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/web/WEB-INF/sun-jaxws.xml b/source/web/WEB-INF/sun-jaxws.xml index 57b9672f85..5d8faa8332 100644 --- a/source/web/WEB-INF/sun-jaxws.xml +++ b/source/web/WEB-INF/sun-jaxws.xml @@ -19,8 +19,10 @@ --> - + + @@ -33,7 +35,7 @@ - - @@ -61,7 +63,7 @@ - - - - - - + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + + + + + + org.apache.chemistry.opencmis.server.impl.webservices.AuthHandler + + + + + diff --git a/source/web/WEB-INF/web.xml b/source/web/WEB-INF/web.xml index 8fc85fc015..83689caf7b 100644 --- a/source/web/WEB-INF/web.xml +++ b/source/web/WEB-INF/web.xml @@ -102,6 +102,12 @@ + + CMIS security context cleaning filter + Cleans security context before authentication via the CMIS services or filters. Mapped only for CMIS + org.alfresco.web.app.servlet.CmisSecurityContextCleanerFilter + + Authentication Filter Authentication filter mapped only to faces URLs. Other URLs generally use proprietary means to talk to the AuthenticationComponent @@ -111,7 +117,7 @@ AuthenticationFilter - + Global Authentication Filter Authentication filter mapped to all authenticated URLs. Mainly for SSO support @@ -182,6 +188,16 @@ Global Localization Filter /* + + + CMIS security context cleaning filter + /cmisws/* + + + + CMIS security context cleaning filter + /cmisatom/* + Global Authentication Filter @@ -366,8 +382,8 @@ - com.sun.xml.ws.transport.http.servlet.WSServletContextListener - + com.sun.xml.ws.transport.http.servlet.WSServletContextListener + @@ -556,31 +572,49 @@ - - cmisws - org.apache.chemistry.opencmis.server.impl.webservices.CmisWebServicesServlet - 7 - + + cmisws10 + org.apache.chemistry.opencmis.server.impl.webservices.CmisWebServicesServlet + + cmisVersion + 1.0 + + 7 + + + + cmisws11 + org.apache.chemistry.opencmis.server.impl.webservices.CmisWebServicesServlet + + cmisVersion + 1.1 + + 7 + - - cmisatom - org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet - - callContextHandler - org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler - - 8 - + + cmisatom10 + org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet + + callContextHandler + org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler + + + cmisVersion + 1.0 + + 8 + - - cmisbrowser - org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet - - callContextHandler - org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler - - 8 - + + cmisbrowser + org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet + + callContextHandler + org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler + + 8 + cmistck @@ -592,6 +626,15 @@ authenticatorServlet org.alfresco.repo.web.scripts.servlet.AuthenticatorServlet + + + publicapiServlet + org.alfresco.rest.api.PublicApiWebScriptServlet + + authenticator + publicapi.authenticator + + @@ -682,7 +725,7 @@ axis - /api/* + /soapapi/* @@ -766,12 +809,12 @@ - cmisws + cmisws10 /cmisws/* - cmisatom + cmisatom10 /cmisatom/* @@ -779,6 +822,11 @@ cmisbrowser /cmisbrowser/* + + + publicapiServlet + /api/* + + SOLR @@ -880,6 +930,8 @@ repoclient + + A flag that globally enables or disables startup of the major Alfresco subsystems. properties/startup.enable diff --git a/source/web/WEB-INF/wsdl/xml.xsd b/source/web/WEB-INF/wsdl/xml.xsd deleted file mode 100644 index 052806ba41..0000000000 --- a/source/web/WEB-INF/wsdl/xml.xsd +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - See http://www.w3.org/TR/xmlbase/ for - information about this attribute. - - - - - - See http://www.w3.org/TR/xml-id/ for - information about this attribute. - - - - - - - - - - - \ No newline at end of file diff --git a/source/web/images/logo/hazelcast.png b/source/web/images/logo/hazelcast.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e23142a7d0d698501f508693a95b77eab6a026 GIT binary patch literal 9834 zcmZ8nQ+VFNv;M`l8taQ~HZ~jEZW`NP(l)lurm<~Xjcqly8lC*l&B4XaJiB`_yR-A` z`_9gWeNmD|K_ox~002c+Mnd&NUwt$gc-Rj~gNjxEp%5HpbX))c3F|)%0!YvN1OSN2 zHsa!6zF0fBI=EOnIFiYVi<3DzJ6PI$vj70kl`J(Yb+seh&kq~7V)CKjM0p2Q9C$KS zu?R4B95p>T0=ir%dEPRPN)LvlBsAf0ZYWfAG&mARg%LR%aS3jZJU{w-L1_5s^R`cc z?Lzy*!Ngm`qR?UaO;+6$TsJ&&vJ8g`7Z|xjj09ur`%wSj_8zlHAR@>SK!>k0CwF1qB%>y5Twj2+vt0c%WM`qnni|I_VNe1e{GdaO&X)%+~PRimjU~`*5nxu;`_j;w_vj=jbZQYCmKyDn) z$8K+4Jtt8sCnve18&Qpzj=NyrDNIdw-}a}<97O<>mdoy(PJRF+Gz}Ex$LbUZZZU*Kbe$f-etu zTb(3W>5(_= zg%n|8@pJ=JGwlh=3b3v)X$D+|4iVsduZDO z5uinf;jv7}S3)67!?h`+;qlUbK9cvyKx0OL$VNi3RVd`+xMbK=!_~<&WQeanJ45n? z=u5T62@C`5K`+7W(rk%=wJM+IkQ>BXig^frNaZ8_F?VH4kHO8&_~Tqp@Hvt@@9_h(MeeD+oLYP(M_9X($qkm;_op0hhuB?1vMSjvOfi<4>gH6?6*H(=6Bod{RKUy&{zBb)Afp81 zd>;z6qQ%en1oz1b-{VtNs={yl*$Dh0bygm>lhngBv@{0|ZTd!fU!1s6#3Z>S>LfyX z7WIX)Szk`n2-U1g1d2mSt%@Dgg@5_$ zyoSN*^eOZyi~mx|tufkdA0$IE!>{vXB)3H=3w8_S>Zh)mSoU?NZ%ch8Zj1O_T9U^n z&LPL4Ri}EBXekW0o9gtK>8gZqNL!S0;~&0(eL=TFNBEmlp@q#t-?lV4C0V;nrc9+w z`lN%q@~kN9cZXz~&T}BD=#U(ZK8>_h%p^?Kq1v+AdJ$p~uHt9@yGrI#+d{&;HVKa| z`=ayI>`p^)wt_>^hF8boKO#StSM^uBe?@oF$l9=V$ROBN;zLc7t|<1=O(A3$0+ z2q+9qj8EiGETnN|d}do@Kg>AHSj^aLGS>CfWo#^NY_^cC-P8T8bKcl)|5KMwr%+o% z*Pu?SBCCRGp{=5=2&1S)DM6_$d%>!&`l@lHv7`yVdVdLawX)H!(a*%n6wj(@ptA2g zp(DYs)i3JxGaO3DGHMyIF0sE$y)!nyCjUnIWahcB-@tA15sQ`f6#CQ>$8ICm7+t?j zmRiQFv=yFJi_7<$(1- zkhPp~&K$aI9S)a2eZ%5gD*MyINI6NYwwvYt%Hqm_Rt<-gEM_cmS`~}cO@$t%4<;9Q zLia+>IlDr;f;=1S8#+egJl##hO=HS^4%tROH^l=e-_75>-=~2hFcpLqR9K*BpdRG& zqqi@4SF|wys>OZn@|kF4Zi^_6XiQK=(0)$^x%KdAYz6tlVd`Yuqz&rNFaCcQ{=k_W zm_+pXBh&m0`Kc8w9PJpYO)$-t!sRi&ChoE+@lPUIVk5(fO_{HXNsfzNsFeAu;0jMG zXRGiav!%}Xympqh>^FHLK4$t#Zu@VYn=fZKAv;++NV`6GsVu_=j$V0_y|+J$a7&mm z8Tpe%6hf7F6E8*4>5FkAsjjg+sG?@ltRCmT1>J_X$HB zM!VA166;IK`diGWEN3i_4mOyw^-z;bQw~y4?NOFj>QOc|>(B1)C0AKeCTLgNzBh`u z6m$tTw_6mAOil<0tN&8JRsW~XeLl0^V6ymVKYdQ<(|*r+I=`yd{_rX^(z&Vup`kc$ zIdAbS`&{=RTp3n+^qBl?XHcPJ=X5p%H3RhuM~T|F*fKXyJo8yyHD-a~L>hI7wDT?N z!h;Eg8$}~3b8v^!QNnBQ=mBB#fdqwr#XZued>d|-)ScLhnB}Wj`gOWghFbcwo~d4| z^0?6S!tsXpi}WffS|+EUj+fkx`iRZSQP6CH)%8?lR#KLqKl9U?@oIjf&!O4m=2tX_ zi&k{k?HS4Uh(m#Pfl2-AX4mW5)qO0jX07xpej~eM*JHuAgjwaGw#>Hl$`*awmUHip z1|Q3ZBf@N+$@SX~uPfa5h52m0&+8pG-VP4~4|kim>;BF(uajeK%N{i6746FHMz2|mf@72@OD5q5q( zdMOg0GM}Q(#(T?u8>_^_W$}NUKUtidPMyw6xlT#wvhyu`J?=iiuUZ}K9VF=-@#J7L zyw!X@>+x9gAigNrL{r}LB@3W^w|=U*Q~Oi&oPeK@@D2@?dh=q&!L<6pH_6OoR22ch zn+gEH-vQw1{X-uCfEz0S92)}we<}drIm84VhwU+4mV)**vN+nrP zvu(NYKC=|Mm>Ai}kF>R6yZ8}>18@81AwejbJ_To3_`@42_WNO!3^x%ghfES2m@+ZesuJ#H0tbVXsAW= zHGENRbj4KXq}~7n1d*JSG33`kI$CCNd0!}S6GUW@nzHECqD9y&L_4Z+j3%U!3F^K} zq*w(T%z%Z+&MJgDr2lewn(xsPM9p0wais7Gj#z(L!@ zf_2~5QaLppiQw1~c|I*|%9}Dvp2T){H@JpTZ0r

Njbi3K(AS7WMdX=GigX+R?|N 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 diff --git a/source/web/images/logo/ibatis.png b/source/web/images/logo/ibatis.png new file mode 100644 index 0000000000000000000000000000000000000000..7a5242d8381748f9defc3f37151c76726010013a GIT binary patch literal 2139 zcmb7``#Td1AI3M$!{oG~oaPX7TsdS7DK--`;2)rKi7R-_x1hd`^%kbZ)YhYBr5~}07P(BSjR)Y zI+Tkb-=X(fnOh$M8186^0n`l1FCGRE32lo80O~W3?)vZ_W^jlVAshe@?fQ>^tl&x_ z03fi2!=jy|Jy#z0=S>)kV_|9L4jK|^7%qojKhaQdg^~YNNmYm=5D83Do&99u7Hy(5 zT3NHt_j&jC+(VUVK|{U=3I78foq|_RJq(WYsQv1!71kfyXL@_Tk=)i+6SYG_j+F7`z5Tib+&j%JwjZypy<`)A&?bE?le`~)Fd6(K$Fu7o_CO>|hAH>M<9(l6+^t!* zn8cIblg&ogaa}P%dycnrfKmODDw=zHYKp208Zd9;bTP*5tXt|)(k|CeOY@|bkkNAC z@XA=`;8?>k*OD8`!_rCRSCrXyigE3@9#uY~(W11w+vk^>8Ixy8soR;hj^BdQ2egs> ztmvd2J4EW56vWiqC4S6<9C2pR7gu;6p~sJcJd<&-BjJ?#KAGa53T*Z1fG}PwYo*Y2-6sMxY$m2#B=pTL6&z%WsJ{YwsxSUWa}?h#9faPw-eqN_9_B6x-J)I8 zf$83^`$=(HK&&&8K$j)%N+Q0Hak@w83)UkNuU^eZuOq+~WtXU{idy6<%#`Vjn^H9^ zUyyZ=eKV^-9OdL67~c&k+tyoss03O?<$O3LtwtPHPOdrn;eGMO`g2SoG$=AVDMv;t zKwkPrhJ5KQr7G&5GMqk8>2_ugq0&|zos76JU+2z#BXlcicBsXyA*A%Gv#P-z=OvKD zVi^Q)EpVw0bk{xa(G%R|s&;1K8$Vp%)*aWYg?F5s z7DN-*aVdDK)&^__&f&cqntGrG8w0Qa7J`ffi}B#ydh+k789L9#I&s^4QQ>OXMH*av z7Vc56>NF-{G|?nNhwC&d|NUzkPYE3SS{;UB#q|cjK1t#A+dytnDH`Q|qOlzASl}aH z$jq~z$%=@@GT!I;Qp~7L z@2XtS_Z!E_;K|LHC=sjl;?Jq4i0XS-`oK{2v9QrSXbb+iVz@Cr?aW)1#TCbM9|KFz z`MjI*4WJ9pF}z@+YrW@sO7s`DD82@F#j4Yb%iZ-XU6`uB2JAh5UpkHOO&IV<>yxjn zOF<6#c3qUY{-_v5QA<8MUU0A*#D#|zS-Fwp8IC^OwJIVG@|0KX;C`Lp_|vWgz=H#s z$&>jW1ip)XvmdD0*I=Y91-ybAKHE4QPE;r>8LH#VfN?fm6!xvSj7$Y$!HN!W8cChqozpy$i$XzR^f`>#`sOVYt&7FwEbsJHN z=XNnte?o!WD-ELrh@KFF_=(Z-RqCr~xx9uBnTsG^wyIsx5Ve@`e5%zXNn@docx7x) z%_*X!TDtl5*KJAK1|}Cq(APC1<#vhUZxo5OUKF1ZBpjU@R9>D$ax$FNmW!fuOCEVm z2&0?yIVMgPysI0s4pxb$|H-B@*7PeBX(p3I+$&qQ%V`xDI_p~xbX3zVCr?>A}!5f|KVsg(t(Beoef_u>Fgk zS!qkI>t6Qum@l|K?V1f?_tthenc(2Q7(vp)6Qzdl_)|FO2zjQ&z?tF3!s z8ybhLrocXQ4ugxjpp24ij(w}))W~w#0>zx@RC#KzaAn>MX<%Yx7FBhDCRs2%^2FRA z)OFK1)zB}Vk*rfTutOjYG!=LHsoCL2jk8h-Z|)mj6CiCJ8?Gln576VaL==m_10s|+Y)FsTD6}a?o9qrYMQ1)+RJ!W=q#8g7ICk@R9uKJIA}=V??lcGL8X@^Dz{gNRZT zXFOmDpEj9qVBYYrZ)fo-!B1ZglqWZna;i=^&C}=bJLWsa3>tw{8~ z)XLj0jUKECk|2z@MqPI+4^Wddxr%!%ZLio?6SnW~1XQ0l*WN!b+U&Qo1iwDV``ms% zd&*9;{R`9kL=G`3chbKBdD-fT literal 0 HcmV?d00001 diff --git a/source/web/images/logo/java.gif b/source/web/images/logo/java.gif index e88f047d11417ef52f1573cb58f5669ac88b49ab..27d1c150366fc2872b7bd458f7d2d0c212f37001 100644 GIT binary patch literal 2790 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 cmN2bPDNB8 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 literal 0 HcmV?d00001 diff --git a/source/web/images/logo/open-office.gif b/source/web/images/logo/open-office.gif deleted file mode 100644 index fc44c00680eaa4d3874c8f9fae3a1dfaf5958960..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1131 zcmV-x1eE(nNk%w1VR`^40M!5hzrVu2zrTNff2ygiiJ8jp@9#iBK-ARM5D*Z=%;cY+ zpH615FfcHWkB{Hq-(X;1P*70M&(G@V>L4H>`uh5CaB#}W%+Jr!udlCcfW0C>oZ;p2 zy1BgH-{8~P>pxkk@bdWY@9?$1-lnqGwY0az#K$pBqI-?Rm!;6JuCiTow)FJ%h($|Ns9000000000000000000000000000000000000000000000000000 z00000EC2ui0D1r@000L6K$vhyEE7i3qm3vE*d8w1O)B@4-6PkM`y%> zgC{l+QQ@MY3m6+5(j(B&-#G=x7?j%r0-r<|BZfE}5pqPs4+#=bbYYPjhBFleBzj@s zi^mTHGB`{iq+vb(AuBENBjDlOOblXXj@n|<#fKp%eDad8;kDzxZs0gE}!v!GbNiehd_d;0MBN z0SZ_-xLagphS5$_Cir|D1ablqD<%+;GoJ?#ZxssJfPz5W(jzuNSBb&{^e1eW3X!c< zhyyfTM?o+n`GFAIF9Jvndk^N#C)$wwiOKT z(bRy2MXKb7M)JseW1Yx-!g>42og$B%oz|+BUuG( zO+c0cGr8HwyQ2WMuVQ*CIwb*nndre=`DCE#m!_H!*S8zsqk&H2I^lqNSSiWHpzhEb xGZmU%g++L&;-g&_J^O40iwy~;MbSo6fh++i46TI&Z_wQI)mUe(wG=@B06Uav+;RW_ diff --git a/source/web/images/logo/solr.png b/source/web/images/logo/solr.png new file mode 100644 index 0000000000000000000000000000000000000000..99d88512d941019a2cd84e1ad4d943e748b5ddd7 GIT binary patch literal 21504 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 literal 0 HcmV?d00001 diff --git a/source/web/jsp/dialog/about.jsp b/source/web/jsp/dialog/about.jsp index 119f4f4052..d9ec12650f 100644 --- a/source/web/jsp/dialog/about.jsp +++ b/source/web/jsp/dialog/about.jsp @@ -1,209 +1,193 @@ -<%-- - * Copyright (C) 2005-2013 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . ---%> -<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> -<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> -<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - -<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> -<%@ page isELIgnored="false" %> -<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> - - - - - - -
- -
- Alfresco -
-
- http://www.alfresco.com -

- Alfresco Software Inc. © 2005-2013 All rights reserved. Legal and License -

- -
- Alfresco Software utilises components or libraries from the following software vendors and companies -
- -

 

- -
- - Spring Framework - - - Hibernate - -
-
- - The Apache Software Foundation - -
-
- - The Apache Jakarta Project - -
-
- - Java - - - JBoss - - - My Faces - -
-
- - Lucene - - - Code Generation Library - -
-
- - PDFBox - - - TinyMCE - - - OpenOffice.org - - - JooReports - - - FreeMarker - -
- -

 

-

 

- -
- Alfresco Development tools: -
- -
- - Subversion - - - eclipse - -
- -

 

-

 

- -
- Alfresco Software contributors -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Meta Data Extraction Framework and PDF/Open Office Format meta data extraction: -  •  - Jesper Steen Møller -
- Open Document Format meta data extraction: -  •  - Antti Jokipii -
- Multilingual Document Management: -  •  - CEC -
- Category Browsing: -  •  - Atol Conseils et Développements -
- Fixes and improvements: -  •  - Ray Gauss II, - Dave Gillen, - Michael Kriske, - Carina Lansing, - DMC.de, - Optaros -
- Language and translation packs: -  •  - Camille Bégnis, - Andrejus Chaliapinas, - Laurent Genier, - Antti Jokipii, - Henning Kristensen, - Betty Mai, - Fabian Mandelbaum, - Theodoros Papageorgiou, - Helio Silvio Piccinatto, - Gian Luca Farina Perseu, - Alex Revesz, - Christian Roy, - Philippe Seillier, - Frank Shipley, - Michiel Steltman, - Gert Thiel, - cnalfresco -
- -
-
+<%-- + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + +
+ +
+ Alfresco +
+
+ http://www.alfresco.com +

+ Alfresco Software Inc. © 2005-2013 All rights reserved. Legal and License +

+ +
+ Alfresco Software utilises components or libraries from the following software vendors and companies +
+ +

 

+ +
+ + Spring Framework + + + Hibernate + +
+
+ + The Apache Software Foundation + +
+
+ + The Apache Jakarta Project + +
+
+ + Java + + + JBoss + + + My Faces + +
+
+ + Lucene + + + Code Generation Library + +
+
+ + PDFBox + + + TinyMCE + + + OpenOffice.org + + + JooReports + + + FreeMarker + +
+ +

 

+

 

+ +
+ Alfresco Development tools: +
+ +
+ + Subversion + + + eclipse + +
+ +

 

+

 

+ +
+ Alfresco Software contributors +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Meta Data Extraction Framework and PDF/Open Office Format meta data extraction: +  •  + Jesper Steen Møller +
+ Open Document Format meta data extraction: +  •  + Antti Jokipii +
+ Multilingual Document Management: +  •  + CEC +
+ Category Browsing: +  •  + Atol Conseils et Développements +
+ Fixes and improvements: +  •  + Ray Gauss II, + Dave Gillen, + Michael Kriske, + Carina Lansing, + DMC.de, + Optaros +
+ Supported language packs: +  •  + French, German, Italian, (European) Spanish and Japanese. +
+ +
+
\ No newline at end of file diff --git a/source/web/jsp/workflow/pooled-tasks-todo-dashlet.jsp b/source/web/jsp/workflow/pooled-tasks-todo-dashlet.jsp index 901947c14d..aee1e78591 100644 --- a/source/web/jsp/workflow/pooled-tasks-todo-dashlet.jsp +++ b/source/web/jsp/workflow/pooled-tasks-todo-dashlet.jsp @@ -79,7 +79,7 @@ - + <%-- Actions column --%> diff --git a/source/web/jsp/workflow/tasks-active-dashlet.jsp b/source/web/jsp/workflow/tasks-active-dashlet.jsp index 191e475528..0ee1e24c4e 100644 --- a/source/web/jsp/workflow/tasks-active-dashlet.jsp +++ b/source/web/jsp/workflow/tasks-active-dashlet.jsp @@ -87,7 +87,7 @@ - + <%-- Actions column --%> diff --git a/source/web/jsp/workflow/tasks-todo-dashlet.jsp b/source/web/jsp/workflow/tasks-todo-dashlet.jsp index eb99d1728b..20836f8756 100644 --- a/source/web/jsp/workflow/tasks-todo-dashlet.jsp +++ b/source/web/jsp/workflow/tasks-todo-dashlet.jsp @@ -74,12 +74,12 @@ - <%-- Priority column --%> + <%-- Priority column --%> - + <%-- Actions column --%> diff --git a/source/web/scripts/ajax/tiny_mce_wcm_extensions.js b/source/web/scripts/ajax/tiny_mce_wcm_extensions.js index b305352346..653c6e2aa8 100644 --- a/source/web/scripts/ajax/tiny_mce_wcm_extensions.js +++ b/source/web/scripts/ajax/tiny_mce_wcm_extensions.js @@ -30,6 +30,9 @@ if (!alfresco.log) alfresco.log = alfresco.constants.DEBUG ? log : Class.empty; } +//MNT-2080: AVM_WEBAPP url rendering in the html view of TinyMCE editor +tinyMCE.avmWebappUrl = alfresco.constants.AVM_WEBAPP_URL; + function alfresco_TinyMCE_urlconverter_callback(href, element, onsave) { var result = null; @@ -47,7 +50,7 @@ function alfresco_TinyMCE_urlconverter_callback(href, element, onsave) } else if (href.startsWith("/")) { - result = alfresco.constants.AVM_WEBAPP_URL + href; + result = alfresco.constants.AVM_WEBAPP_URL + href; } else if (href.startsWith(document.location.href)) { diff --git a/source/web/scripts/tiny_mce/themes/advanced/js/source_editor.js b/source/web/scripts/tiny_mce/themes/advanced/js/source_editor.js index 279328614c..fe5fd69015 100644 --- a/source/web/scripts/tiny_mce/themes/advanced/js/source_editor.js +++ b/source/web/scripts/tiny_mce/themes/advanced/js/source_editor.js @@ -13,7 +13,13 @@ function onLoadInit() { if (tinymce.isGecko) document.body.spellcheck = tinyMCEPopup.editor.getParam("gecko_spellcheck"); - document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent({source_view : true}); + //MNT-2080: AVM_WEBAPP url rendering in the html view of TinyMCE editor + var src = tinyMCEPopup.editor.getContent({source_view : true}); + + if (tinyMCE.avmWebappUrl != null) + src = src.replace(new RegExp(tinyMCE.avmWebappUrl, 'g'), ""); + + document.getElementById('htmlSource').value = src; if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) { setWrap('soft');