Skip to content
Browse files

GTNPORTAL-1956 Public API

 - Navigation API
 - Initial support for Pages and Sites
  • Loading branch information...
1 parent 15d6512 commit e21ea6faffec3852caf29eeb0c14093472a1edc6 @nscavell nscavell committed with bdaw Feb 4, 2013
Showing with 8,319 additions and 79 deletions.
  1. +131 −0 component/api/pom.xml
  2. +106 −0 component/api/src/main/java/org/gatein/api/BasicPortalRequest.java
  3. +101 −0 component/api/src/main/java/org/gatein/api/Comparators.java
  4. +437 −0 component/api/src/main/java/org/gatein/api/PortalImpl.java
  5. +219 −0 component/api/src/main/java/org/gatein/api/Util.java
  6. +40 −0 component/api/src/main/java/org/gatein/api/management/GateInApiManagementExtension.java
  7. +522 −0 component/api/src/main/java/org/gatein/api/management/GateInApiManagementResource.java
  8. +428 −0 component/api/src/main/java/org/gatein/api/management/NavigationManagementResource.java
  9. +151 −0 component/api/src/main/java/org/gatein/api/management/PageManagementResource.java
  10. +298 −0 component/api/src/main/java/org/gatein/api/management/Utils.java
  11. +312 −0 component/api/src/main/java/org/gatein/api/navigation/ApiFilteredNode.java
  12. +590 −0 component/api/src/main/java/org/gatein/api/navigation/ApiNode.java
  13. +234 −0 component/api/src/main/java/org/gatein/api/navigation/ApiNodeChange.java
  14. +46 −0 component/api/src/main/java/org/gatein/api/navigation/ApiNodeModel.java
  15. +79 −0 component/api/src/main/java/org/gatein/api/navigation/MultiPathNodeVisitor.java
  16. +98 −0 component/api/src/main/java/org/gatein/api/navigation/Navigation18NResolver.java
  17. +273 −0 component/api/src/main/java/org/gatein/api/navigation/NavigationImpl.java
  18. +98 −0 component/api/src/main/java/org/gatein/api/navigation/NodeVisitorScope.java
  19. +114 −0 component/api/src/main/java/org/gatein/api/navigation/ObjectFactory.java
  20. +137 −0 component/api/src/main/java/org/gatein/api/page/PageImpl.java
  21. +299 −0 component/api/src/main/java/org/gatein/api/site/SiteImpl.java
  22. +1 −0 component/api/src/main/resources/META-INF/services/org.gatein.management.spi.ManagementExtension
  23. +33 −0 component/api/src/main/resources/conf/portal/configuration.xml
  24. +163 −0 component/api/src/test/java/org/gatein/api/AbstractApiTest.java
  25. +61 −0 component/api/src/test/java/org/gatein/api/Assert.java
  26. +928 −0 component/api/src/test/java/org/gatein/api/PortalImplTest.java
  27. +47 −0 component/api/src/test/java/org/gatein/api/SerializationUtils.java
  28. +281 −0 component/api/src/test/java/org/gatein/api/navigation/ApiFilteredNodeTest.java
  29. +435 −0 component/api/src/test/java/org/gatein/api/navigation/ApiNodeTest.java
  30. +604 −0 component/api/src/test/java/org/gatein/api/navigation/NavigationImplTest.java
  31. +95 −0 component/api/src/test/java/org/gatein/api/navigation/NodeVisitorScopeTest.java
  32. +35 −0 component/api/src/test/resources/conf/exo.portal.component.api-configuration.xml
  33. +1 −1 component/common/src/main/java/org/gatein/common/xml/stax/writer/StaxWriterImpl.java
  34. +3 −5 component/common/src/main/java/org/gatein/common/xml/stax/writer/StaxWriterUtils.java
  35. +4 −0 component/common/src/main/java/org/gatein/common/xml/stax/writer/builder/StaxWriterBuilder.java
  36. +13 −3 component/common/src/main/java/org/gatein/common/xml/stax/writer/builder/StaxWriterBuilderImpl.java
  37. +5 −1 component/common/src/main/java/org/gatein/common/xml/stax/writer/formatting/NoOpFormatter.java
  38. +51 −0 component/management/src/main/java/org/gatein/management/runtime/ExternalContextImpl.java
  39. +4 −0 component/management/src/main/resources/conf/portal/configuration.xml
  40. +1 −0 component/pom.xml
  41. +17 −0 component/portal/src/main/java/org/exoplatform/portal/config/NewPortalConfigListener.java
  42. +9 −0 component/portal/src/main/java/org/exoplatform/portal/config/UserPortalConfigService.java
  43. +6 −6 component/portal/src/main/java/org/exoplatform/portal/mop/management/MopManagementExtension.java
  44. +3 −2 component/portal/src/main/java/org/exoplatform/portal/mop/management/binding/MopBindingProvider.java
  45. +9 −3 .../portal/src/main/java/org/exoplatform/portal/mop/management/binding/xml/NavigationMarshaller.java
  46. +9 −3 component/portal/src/main/java/org/exoplatform/portal/mop/management/binding/xml/PageMarshaller.java
  47. +9 −3 .../portal/src/main/java/org/exoplatform/portal/mop/management/binding/xml/SiteLayoutMarshaller.java
  48. +1 −1 ...portal/src/main/java/org/exoplatform/portal/mop/management/exportimport/NavigationExportTask.java
  49. +1 −1 ...onent/portal/src/main/java/org/exoplatform/portal/mop/management/exportimport/PageExportTask.java
  50. +1 −1 ...portal/src/main/java/org/exoplatform/portal/mop/management/exportimport/SiteLayoutExportTask.java
  51. +2 −2 ...l/src/main/java/org/exoplatform/portal/mop/management/operations/AbstractMopOperationHandler.java
  52. +2 −2 ...nent/portal/src/main/java/org/exoplatform/portal/mop/management/operations/MopImportResource.java
  53. +2 −2 component/portal/src/main/java/org/exoplatform/portal/mop/management/operations/MopReadResource.java
  54. +25 −0 ...portal/src/main/java/org/exoplatform/portal/mop/management/operations/SecureOperationHandler.java
  55. +2 −2 ...org/exoplatform/portal/mop/management/operations/navigation/FilteredNavigationExportResource.java
  56. +1 −1 ...mop/management/operations/navigation/{NavigationReadConfigAsXml.java → NavigationReadConfig.java}
  57. +2 −4 ...xoplatform/portal/mop/management/operations/page/{PageReadConfigAsXml.java → PageReadConfig.java}
  58. +5 −1 ...ortal/mop/management/operations/site/{SiteLayoutReadConfigAsXml.java → SiteLayoutReadConfig.java}
  59. +11 −0 component/portal/src/main/java/org/exoplatform/portal/mop/navigation/NodeContext.java
  60. +1 −1 ...tal/src/test/java/org/exoplatform/portal/mop/management/binding/xml/NavigationMarshallerTest.java
  61. +2 −2 ...nt/portal/src/test/java/org/exoplatform/portal/mop/management/binding/xml/PageMarshallerTest.java
  62. +3 −1 ...tal/src/test/java/org/exoplatform/portal/mop/management/binding/xml/SiteLayoutMarshallerTest.java
  63. +15 −0 component/resources/pom.xml
  64. +4 −0 component/web/controller/src/main/java/org/exoplatform/web/WebAppController.java
  65. +92 −0 component/web/controller/src/main/java/org/exoplatform/web/url/simple/SimpleURL.java
  66. +193 −0 component/web/controller/src/main/java/org/exoplatform/web/url/simple/SimpleURLContext.java
  67. +43 −0 component/web/controller/src/main/java/org/exoplatform/web/url/simple/SimpleURLFactoryPlugin.java
  68. +5 −0 examples/portlets/api/pom.xml
  69. +106 −0 examples/portlets/api/src/main/java/org/gatein/portal/samples/api/NavigationPortlet.java
  70. +17 −29 examples/portlets/api/src/main/webapp/WEB-INF/portlet.xml
  71. +1 −1 ...dgets/src/main/java/org/gatein/management/gadget/mop/exportimport/server/FileDownloadServlet.java
  72. +2 −0 packaging/jboss-as7/modules/build.xml
  73. +15 −0 packaging/jboss-as7/modules/pom.xml
  74. +1 −0 packaging/jboss-as7/modules/src/main/resources/modules/org/gatein/lib/main/module.xml
  75. +14 −0 packaging/jetty/pkg/pom.xml
  76. +14 −0 packaging/tomcat/pkg/pom.xml
  77. +24 −1 pom.xml
  78. +35 −0 web/portal/src/main/webapp/WEB-INF/conf/api/api-configuration.xml
  79. +1 −0 web/portal/src/main/webapp/WEB-INF/conf/configuration.xml
  80. +5 −0 web/portal/src/main/webapp/WEB-INF/conf/portal/controller-configuration.xml
  81. +5 −0 web/portal/src/main/webapp/WEB-INF/conf/portal/portal-configuration.xml
  82. +10 −0 webui/portal/pom.xml
  83. +3 −0 webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestHandler.java
  84. +113 −0 webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestImpl.java
View
131 component/api/pom.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2012, Red Hat, Inc., and individual contributors
+ ~ as indicated by the @author tags. See the copyright.txt file in the
+ ~ distribution for a full listing of individual contributors.
+ ~
+ ~ This 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 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software 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 this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component</artifactId>
+ <version>3.6.0.MO1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>exo.portal.component.api</artifactId>
+ <packaging>jar</packaging>
+ <name>GateIn Portal Component API Implementation</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.gatein.api</groupId>
+ <artifactId>gatein-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.common</groupId>
+ <artifactId>common-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.portal</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.web.controller</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.web.resources</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.resources</artifactId>
+ </dependency>
+ <!-- For mgmt (rest) of api -->
+ <dependency>
+ <groupId>org.gatein.management</groupId>
+ <artifactId>gatein-management-spi</artifactId>
+ </dependency>
+ <!-- For testing -->
+ <dependency>
+ <groupId>org.chromattic</groupId>
+ <artifactId>chromattic.core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.test.core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.test.jcr</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.portal</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.identity</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.gatein.portal</groupId>
+ <artifactId>exo.portal.component.resources</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkMode>always</forkMode>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
View
106 component/api/src/main/java/org/gatein/api/BasicPortalRequest.java
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api;
+
+import org.gatein.api.common.URIResolver;
+import org.gatein.api.navigation.NodePath;
+import org.gatein.api.security.User;
+import org.gatein.api.site.SiteId;
+
+import java.util.Locale;
+
+/**
+ * A basic portal request supplying all the information needed in the constructor.
+ *
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+public class BasicPortalRequest extends PortalRequest {
+ private final User user;
+ private final SiteId siteId;
+ private final NodePath nodePath;
+ private final Locale locale;
+ private final Portal portal;
+ private final URIResolver uriResolver;
+
+ public BasicPortalRequest(User user, SiteId siteId, NodePath nodePath, Locale locale, Portal portal, URIResolver uriResolver) {
+ this.user = user;
+ this.siteId = siteId;
+ this.nodePath = nodePath;
+ this.locale = locale;
+ this.portal = portal;
+ this.uriResolver = uriResolver;
+ }
+
+ @Override
+ public User getUser() {
+ return user;
+ }
+
+ @Override
+ public SiteId getSiteId() {
+ return siteId;
+ }
+
+ @Override
+ public NodePath getNodePath() {
+ return nodePath;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return locale;
+ }
+
+ @Override
+ public Portal getPortal() {
+ return portal;
+ }
+
+ @Override
+ public URIResolver getURIResolver() {
+ return uriResolver;
+ }
+
+ public static void setInstance(BasicPortalRequest request) {
+ PortalRequest.setInstance(request);
+ }
+
+ public static class BasicURIResolver implements URIResolver {
+
+ private String portalURI;
+
+ public BasicURIResolver(String portalURI) {
+ this.portalURI = portalURI;
+ }
+
+ @Override
+ public String resolveURI(SiteId siteId) {
+ String name = siteId.getName();
+ if (name.charAt(0) == '/') {
+ return portalURI + name;
+ } else {
+ return portalURI + "/" + name;
+ }
+ }
+ }
+}
View
101 component/api/src/main/java/org/gatein/api/Comparators.java
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api;
+
+import java.util.Comparator;
+
+import org.exoplatform.portal.config.model.PortalConfig;
+import org.gatein.api.common.Sorting;
+import org.gatein.api.page.Page;
+import org.gatein.api.site.Site;
+import org.gatein.api.site.SiteImpl;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+class Comparators {
+ public static Comparator<PortalConfig> site(final Sorting<Site> sorting) {
+ if (sorting == null) {
+ return null;
+ } else if (sorting.getComparator() == null) {
+ return new Comparator<PortalConfig>() {
+ @Override
+ public int compare(PortalConfig o1, PortalConfig o2) {
+ Site site = new SiteImpl(o1);
+ Site other = new SiteImpl(o2);
+ if (sorting.getOrder() == Sorting.Order.descending) {
+ Site tmp = site;
+ site = other;
+ other = tmp;
+ }
+
+ return site.compareTo(other);
+ }
+ };
+ } else {
+ return new ComparatorWrapper<Site, PortalConfig>(sorting.getComparator()) {
+
+ @Override
+ protected Site from(PortalConfig entity) {
+ return new SiteImpl(entity);
+ }
+ };
+ }
+ }
+
+ public static Comparator<Page> page(final Sorting<Page> sorting) {
+ if (sorting == null) {
+ return null;
+ } else if (sorting.getComparator() == null) {
+ return new Comparator<Page>() {
+ @Override
+ public int compare(Page page, Page other) {
+ if (sorting.getOrder() == Sorting.Order.descending) {
+ Page tmp = page;
+ page = other;
+ other = tmp;
+ }
+
+ return page.compareTo(other);
+ }
+ };
+ } else {
+ return sorting.getComparator();
+ }
+ }
+
+ private abstract static class ComparatorWrapper<T, F> implements Comparator<F> {
+ private final Comparator<T> comparator;
+
+ public ComparatorWrapper(Comparator<T> comparator) {
+ this.comparator = comparator;
+ }
+
+ @Override
+ public int compare(F o1, F o2) {
+ return comparator.compare(from(o1), from(o2));
+ }
+
+ protected abstract T from(F entity);
+ }
+}
View
437 component/api/src/main/java/org/gatein/api/PortalImpl.java
@@ -0,0 +1,437 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api;
+
+import org.exoplatform.commons.utils.ListAccess;
+import org.exoplatform.portal.config.DataStorage;
+import org.exoplatform.portal.config.Query;
+import org.exoplatform.portal.config.UserACL;
+import org.exoplatform.portal.config.UserPortalConfigService;
+import org.exoplatform.portal.config.model.PortalConfig;
+import org.exoplatform.portal.config.model.PortalProperties;
+import org.exoplatform.portal.mop.QueryResult;
+import org.exoplatform.portal.mop.SiteKey;
+import org.exoplatform.portal.mop.description.DescriptionService;
+import org.exoplatform.portal.mop.navigation.NavigationContext;
+import org.exoplatform.portal.mop.navigation.NavigationService;
+import org.exoplatform.portal.mop.page.PageContext;
+import org.exoplatform.portal.mop.page.PageError;
+import org.exoplatform.portal.mop.page.PageService;
+import org.exoplatform.portal.mop.page.PageServiceException;
+import org.exoplatform.portal.mop.page.PageServiceImpl;
+import org.exoplatform.portal.mop.page.PageServiceWrapper;
+import org.exoplatform.portal.mop.page.PageState;
+import org.exoplatform.portal.resource.SkinService;
+import org.exoplatform.services.resources.LocaleConfigService;
+import org.exoplatform.services.resources.ResourceBundleManager;
+import org.exoplatform.services.security.Authenticator;
+import org.exoplatform.services.security.Identity;
+import org.exoplatform.services.security.IdentityConstants;
+import org.exoplatform.services.security.IdentityRegistry;
+import org.gatein.api.common.Filter;
+import org.gatein.api.common.Pagination;
+import org.gatein.api.internal.Parameters;
+import org.gatein.api.internal.StringJoiner;
+import org.gatein.api.navigation.Navigation;
+import org.gatein.api.navigation.NavigationImpl;
+import org.gatein.api.page.Page;
+import org.gatein.api.page.PageId;
+import org.gatein.api.page.PageImpl;
+import org.gatein.api.page.PageQuery;
+import org.gatein.api.security.Permission;
+import org.gatein.api.security.User;
+import org.gatein.api.site.Site;
+import org.gatein.api.site.SiteId;
+import org.gatein.api.site.SiteImpl;
+import org.gatein.api.site.SiteQuery;
+import org.gatein.api.site.SiteType;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:boleslaw.dawidowicz@redhat.com">Boleslaw Dawidowicz</a>
+ * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class PortalImpl implements Portal {
+ private static final Query<PortalConfig> SITES = new Query<PortalConfig>(
+ org.exoplatform.portal.mop.SiteType.PORTAL.getName(), null, PortalConfig.class);
+ private static final Query<PortalConfig> SPACES = new Query<PortalConfig>(
+ org.exoplatform.portal.mop.SiteType.GROUP.getName(), null, PortalConfig.class);
+ private static final Query<PortalConfig> DASHBOARDS = new Query<PortalConfig>(
+ org.exoplatform.portal.mop.SiteType.USER.getName(), null, PortalConfig.class);
+
+ static final Logger log = LoggerFactory.getLogger("org.gatein.api");
+
+ private final DataStorage dataStorage;
+ private final PageService pageService;
+ private final NavigationService navigationService;
+ private final DescriptionService descriptionService;
+ private final ResourceBundleManager bundleManager;
+ private final UserACL acl;
+ private final Authenticator authenticator;
+ private final IdentityRegistry identityRegistry;
+ private final UserPortalConfigService userPortalConfigService;
+
+ public PortalImpl(DataStorage dataStorage, PageService pageService, NavigationService navigationService,
+ DescriptionService descriptionService, ResourceBundleManager bundleManager, Authenticator authenticator,
+ IdentityRegistry identityRegistry, UserACL acl, UserPortalConfigService userPortalConfigService) {
+ this.dataStorage = dataStorage;
+ this.pageService = pageService;
+ this.navigationService = navigationService;
+ this.descriptionService = descriptionService;
+ this.bundleManager = bundleManager;
+ this.authenticator = authenticator;
+ this.identityRegistry = identityRegistry;
+ this.acl = acl;
+ this.userPortalConfigService = userPortalConfigService;
+ }
+
+ @Override
+ public Site getSite(SiteId siteId) {
+ Parameters.requireNonNull(siteId, "siteId");
+ SiteKey siteKey = Util.from(siteId);
+
+ try {
+ PortalConfig portalConfig = dataStorage.getPortalConfig(siteKey.getTypeName(), siteKey.getName());
+ return (portalConfig == null) ? null : new SiteImpl(portalConfig);
+ } catch (Throwable e) {
+ throw new ApiException("Failed to get site", e);
+ }
+ }
+
+ @Override
+ public Site createSite(SiteId siteId) {
+ String template = userPortalConfigService.getDefaultPortalTemplate();
+ if (template == null) {
+ template = ""; // This is valid if we're being executed within a test environment
+ }
+ return createSite(siteId, template);
+ }
+
+ @Override
+ public Site createSite(SiteId siteId, String templateName) throws IllegalArgumentException, EntityAlreadyExistsException {
+ if (getSite(siteId) != null) {
+ throw new EntityAlreadyExistsException("Cannot create site. Site " + siteId + " already exists.");
+ }
+ Parameters.requireNonNull(templateName, "templateName");
+
+ // Create new site
+ return new SiteImpl(siteId, templateName);
+ }
+
+ @Override
+ public List<Site> findSites(SiteQuery query) {
+ Parameters.requireNonNull(query, "query");
+
+ Pagination pagination = query.getPagination();
+ if (pagination != null && query.getSiteTypes().size() > 1) {
+ pagination = null; // set it to null so the internal DataStorage doesn't use it, and we manually page later
+ log.warn("Pagination is not supported internally for SiteQuery's with multiple site types. Therefore this query has the possibility to perform poorly.");
+ }
+
+ List<Site> sites = new ArrayList<Site>();
+ for (SiteType type : query.getSiteTypes()) {
+ List<PortalConfig> internalSites;
+ switch (type) {
+ case SITE:
+ internalSites = findSites(pagination, SITES, Comparators.site(query.getSorting()));
+ break;
+ case SPACE:
+ internalSites = findSites(pagination, SPACES, Comparators.site(query.getSorting()));
+ break;
+ case DASHBOARD:
+ internalSites = findSites(pagination, DASHBOARDS, Comparators.site(query.getSorting()));
+ break;
+ default:
+ throw new AssertionError();
+ }
+
+ sites.addAll(fromList(internalSites, navigationService, query.isIncludeEmptySites()));
+ }
+
+ filter(sites, query.getFilter());
+
+ // Manually do paging for multiple site types.
+ if (query.getSiteTypes().size() > 1) {
+ sites = paginate(sites, query.getPagination());
+ }
+
+ return sites;
+ }
+
+ private <T> List<T> findSites(Pagination pagination, Query<T> query, Comparator<T> comparator) {
+ try {
+ if (pagination != null) {
+ ListAccess<T> access = dataStorage.find2(query, comparator);
+ int size = access.getSize();
+ int offset = pagination.getOffset();
+ int limit = pagination.getLimit();
+ if (offset >= size) {
+ return Collections.emptyList();
+ } else if (offset + limit > size) {
+ return Arrays.asList(access.load(offset, size - offset));
+ } else {
+ return Arrays.asList(access.load(offset, limit));
+ }
+ } else {
+ return dataStorage.find(query, comparator).getAll();
+ }
+ } catch (Throwable e) {
+ throw new ApiException("Failed to query for sites", e);
+ }
+ }
+
+ @Override
+ public void saveSite(Site site) {
+ Parameters.requireNonNull(site, "site");
+ ((SiteImpl) site).save(dataStorage, userPortalConfigService);
+ }
+
+ @Override
+ public boolean removeSite(SiteId siteId) {
+ Site site = getSite(siteId);
+ if (site == null) {
+ return false;
+ }
+ SiteKey siteKey = Util.from(Parameters.requireNonNull(siteId, "siteId"));
+ PortalConfig data = new PortalConfig(siteKey.getTypeName(), siteKey.getName());
+ try {
+ dataStorage.remove(data);
+ return true;
+ } catch (Throwable t) {
+ throw new ApiException("Failed to remove site " + siteId, t);
+ }
+ }
+
+ @Override
+ public Navigation getNavigation(SiteId siteId) {
+ Parameters.requireNonNull(siteId, "siteId");
+
+ try {
+ NavigationContext ctx = navigationService.loadNavigation(Util.from(siteId));
+ if (ctx == null) return null;
+
+ return new NavigationImpl(siteId, navigationService, ctx, descriptionService, bundleManager);
+ } catch (Throwable t) {
+ throw new ApiException("Failed to load navigation", t);
+ }
+ }
+
+ @Override
+ public Page getPage(PageId pageId) {
+ Parameters.requireNonNull(pageId, "pageId");
+
+ try {
+ PageContext context = pageService.loadPage(Util.from(pageId));
+ return (context == null) ? null : new PageImpl(context);
+ } catch (Throwable e) {
+ throw new ApiException("Failed to get page", e);
+ }
+ }
+
+ @Override
+ public Page createPage(PageId pageId) throws EntityAlreadyExistsException {
+ if (getPage(pageId) != null) {
+ throw new EntityAlreadyExistsException("Cannot create page. Page " + pageId + " already exists.");
+ }
+
+ if (getSite(pageId.getSiteId()) == null) {
+ throw new EntityNotFoundException("Site " + pageId.getSiteId() + " doesn't exist");
+ }
+
+ Permission access = Permission.everyone();
+ Permission edit = Permission.any("platform", "administrators");
+ PageState pageState = new PageState(pageId.getPageName(), null, false, null, Arrays.asList(Util.from(access)),
+ Util.from(edit)[0]);
+
+ PageImpl p = new PageImpl(new PageContext(Util.from(pageId), pageState));
+ p.setCreate(true);
+ return p;
+ }
+
+ @Override
+ public List<Page> findPages(PageQuery query) {
+ Pagination pagination = query.getPagination();
+ Iterator<PageContext> iterator;
+ if (pagination == null) {
+ if (query.getSiteType() == null || query.getSiteName() == null)
+ throw new IllegalArgumentException("Pagination is required when site type or site name is null.");
+
+ SiteKey siteKey = Util.from(new SiteId(query.getSiteType(), query.getSiteName()));
+ if (pageService instanceof PageServiceImpl) {
+ iterator = ((PageServiceImpl) pageService).loadPages(siteKey).iterator();
+ } else if (pageService instanceof PageServiceWrapper) {
+ iterator = ((PageServiceWrapper) pageService).loadPages(siteKey).iterator();
+ } else {
+ throw new RuntimeException("Unable to retrieve all pages for " + siteKey);
+ }
+ } else {
+ QueryResult<PageContext> result = pageService.findPages(pagination.getOffset(), pagination.getLimit(),
+ Util.from(query.getSiteType()), query.getSiteName(), null, query.getDisplayName());
+
+ iterator = result.iterator();
+ }
+
+ List<Page> pages = new ArrayList<Page>();
+ while (iterator.hasNext()) {
+ pages.add(new PageImpl(iterator.next()));
+ }
+
+ filter(pages, query.getFilter());
+
+ return pages;
+ }
+
+ @Override
+ public void savePage(Page page) {
+ Parameters.requireNonNull(page, "page");
+
+ if (getSite(page.getSiteId()) == null) {
+ throw new EntityNotFoundException("Site " + page.getSiteId() + " doesn't exist");
+ }
+
+ if (((PageImpl) page).isCreate() && getPage(page.getId()) != null) {
+ // There is still a small chance someone else creates the page, but this is currently the best we can do
+ throw new EntityAlreadyExistsException("Cannot create page. Page " + page.getId() + " already exists.");
+ }
+
+ PageContext context = ((PageImpl) page).getPageContext();
+
+ try {
+ pageService.savePage(context);
+ } catch (Throwable t) {
+ throw new ApiException("Failed to save page " + page.getId(), t);
+ }
+ }
+
+ @Override
+ public boolean removePage(PageId pageId) {
+ Parameters.requireNonNull(pageId, "pageId");
+
+ try {
+ return pageService.destroyPage(Util.from(pageId));
+ } catch (PageServiceException e) {
+ if (e.getError() == PageError.NO_SITE) {
+ throw new EntityNotFoundException("Cannot remove page '" + pageId.getPageName() + "'. Site " + pageId.getSiteId() + " does not exist.");
+ } else {
+ throw new ApiException("Failed to remove page " + pageId, e);
+ }
+ } catch (Throwable t) {
+ throw new ApiException("Failed to remove page " + pageId, t);
+ }
+ }
+
+ @Override
+ public boolean hasPermission(User user, Permission permission) {
+ String expPerm = StringJoiner.joiner(",").join(Util.from(permission));
+
+ Identity identity;
+ if (user == User.anonymous()) {
+ identity = new Identity(IdentityConstants.ANONIM);
+ } else {
+ try {
+ identity = identityRegistry.getIdentity(user.getId());
+ } catch (Throwable t) {
+ throw new ApiException("Failed top retrieve identity", t);
+ }
+ }
+
+ if (identity == null) {
+ try {
+ identity = authenticator.createIdentity(user.getId());
+ } catch (Throwable t) {
+ throw new ApiException("Failed to retrieve user identity", t);
+ }
+
+ if (identity == null) {
+ throw new EntityNotFoundException("User not found");
+ }
+
+ try {
+ identityRegistry.register(identity);
+ } catch (Throwable t) {
+ throw new ApiException("Failed to register identity", t);
+ }
+ }
+
+ try {
+ return acl.hasPermission(identity, expPerm);
+ } catch (Throwable t) {
+ throw new ApiException("Failed to check permissions", t);
+ }
+ }
+
+ private static <T> void filter(List<T> list, Filter<T> filter) {
+ if (filter == null)
+ return;
+
+ for (Iterator<T> iterator = list.iterator(); iterator.hasNext(); ) {
+ if (!filter.accept(iterator.next())) {
+ iterator.remove();
+ }
+ }
+ }
+
+ private static <T> List<T> paginate(List<T> list, Pagination pagination) {
+ if (pagination == null)
+ return list;
+ if (pagination.getOffset() >= list.size())
+ return Collections.emptyList();
+
+ if (pagination.getOffset() + pagination.getLimit() > list.size()) {
+ return new ArrayList<T>(list.subList(pagination.getOffset(), list.size()));
+ } else {
+ return new ArrayList<T>(list.subList(pagination.getOffset(), pagination.getOffset() + pagination.getLimit()));
+ }
+ }
+
+ private static List<Site> fromList(List<PortalConfig> internalSites, NavigationService service, boolean includeAllSites) {
+ List<Site> sites = new ArrayList<Site>(internalSites.size());
+ for (PortalConfig internalSite : internalSites) {
+ NavigationContext ctx = null;
+ if (!includeAllSites) {
+ try {
+ ctx = service.loadNavigation(new SiteKey(internalSite.getType(), internalSite.getName()));
+ } catch (Throwable t) {
+ throw new ApiException("Failed to find sites", t);
+ }
+ }
+
+ if (includeAllSites || ctx != null) {
+ sites.add(new SiteImpl(internalSite));
+ }
+ }
+ return sites;
+ }
+}
View
219 component/api/src/main/java/org/gatein/api/Util.java
@@ -0,0 +1,219 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api;
+
+import org.apache.commons.lang.LocaleUtils;
+import org.exoplatform.portal.config.model.Properties;
+import org.exoplatform.portal.mop.SiteKey;
+import org.exoplatform.portal.mop.page.PageKey;
+import org.gatein.api.common.Attributes;
+import org.gatein.api.page.PageId;
+import org.gatein.api.security.Group;
+import org.gatein.api.security.Membership;
+import org.gatein.api.security.Permission;
+import org.gatein.api.security.User;
+import org.gatein.api.site.Site;
+import org.gatein.api.site.SiteId;
+import org.gatein.api.site.SiteType;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+public class Util {
+
+ public static Properties from(Attributes attributes) {
+ if (attributes == null) {
+ return null;
+ }
+
+ Properties properties = new Properties();
+ properties.putAll(attributes);
+
+ for (String key : properties.keySet()) {
+ if (key.equals(Site.AttributeKeys.SHOW_PORTLET_INFO_BAR.getName())) {
+ String value = properties.get(key);
+ boolean show = Boolean.parseBoolean(value);
+ if (show) {
+ properties.put(key, "1");
+ } else {
+ properties.put(key, "0");
+ }
+ }
+ }
+ return properties;
+ }
+
+ public static Attributes from(Properties properties) {
+ if (properties == null) {
+ return new Attributes();
+ }
+
+ Attributes attributes = new Attributes();
+ for (Entry<String, String> e : properties.entrySet()) {
+ String key = e.getKey();
+ String value = e.getValue();
+ if (key.equals(Site.AttributeKeys.SHOW_PORTLET_INFO_BAR.getName())) {
+ if ("0".equals(value)) {
+ attributes.put(Site.AttributeKeys.SHOW_PORTLET_INFO_BAR, Boolean.FALSE);
+ } else if ("1".equals(value)) {
+ attributes.put(Site.AttributeKeys.SHOW_PORTLET_INFO_BAR, Boolean.TRUE);
+ } else {
+ attributes.put(key, value);
+ }
+ } else {
+ attributes.put(key, value);
+ }
+ }
+ return attributes;
+ }
+
+ public static PageId from(PageKey pageKey) {
+ if (pageKey == null)
+ return null;
+
+ SiteKey siteKey = pageKey.getSite();
+ switch (pageKey.getSite().getType()) {
+ case PORTAL:
+ return new PageId(siteKey.getName(), pageKey.getName());
+ case GROUP:
+ return new PageId(new Group(siteKey.getName()), pageKey.getName());
+ case USER:
+ return new PageId(new User(siteKey.getName()), pageKey.getName());
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public static PageKey from(PageId pageId) {
+ if (pageId == null)
+ return null;
+
+ return new PageKey(from(pageId.getSiteId()), pageId.getPageName());
+ }
+
+ public static SiteId from(SiteKey siteKey) {
+ if (siteKey == null)
+ return null;
+
+ switch (siteKey.getType()) {
+ case PORTAL:
+ return new SiteId(siteKey.getName());
+ case GROUP:
+ return new SiteId(new Group(siteKey.getName()));
+ case USER:
+ return new SiteId(new User(siteKey.getName()));
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public static SiteKey from(SiteId siteId) {
+ if (siteId == null)
+ return null;
+
+ switch (siteId.getType()) {
+ case SITE:
+ return SiteKey.portal(siteId.getName());
+ case SPACE:
+ return SiteKey.group(siteId.getName());
+ case DASHBOARD:
+ return SiteKey.user(siteId.getName());
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public static org.exoplatform.portal.mop.SiteType from(SiteType siteType) {
+ if (siteType == null)
+ return null;
+
+ switch (siteType) {
+ case SITE:
+ return org.exoplatform.portal.mop.SiteType.PORTAL;
+ case SPACE:
+ return org.exoplatform.portal.mop.SiteType.GROUP;
+ case DASHBOARD:
+ return org.exoplatform.portal.mop.SiteType.USER;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public static Permission from(String... permissions) {
+ if (permissions == null)
+ return null;
+ if (permissions.length == 1 && permissions[0] == null)
+ return null; // for some reason this is happening...
+
+ return from(Arrays.asList(permissions));
+ }
+
+ public static Permission from(List<String> permissions) {
+ if (permissions == null)
+ return null;
+
+ if (permissions.size() == 1 && permissions.get(0).equals("Everyone")) {
+ return Permission.everyone();
+ } else {
+ Set<Membership> memberships = new LinkedHashSet<Membership>(permissions.size());
+ for (String permission : permissions) {
+ memberships.add(Membership.fromString(permission));
+ }
+
+ return new Permission(memberships);
+ }
+ }
+
+ public static String[] from(Permission permission) {
+ if (permission == null)
+ return null;
+
+ if (permission.isAccessibleToEveryone()) {
+ return new String[] { "Everyone" };
+ } else {
+ String[] permissions = new String[permission.getMemberships().size()];
+ Iterator<Membership> memberships = permission.getMemberships().iterator();
+ for (int i = 0; i < permissions.length; i++) {
+ permissions[i] = memberships.next().toString();
+ }
+
+ return permissions;
+ }
+ }
+
+ public static Locale toLocale(String locale) {
+ return LocaleUtils.toLocale(locale);
+ }
+
+ public static String fromLocale(Locale locale) {
+ return locale.toString();
+ }
+}
View
40 component/api/src/main/java/org/gatein/api/management/GateInApiManagementExtension.java
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api.management;
+
+import org.gatein.management.spi.ExtensionContext;
+import org.gatein.management.spi.ManagementExtension;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+public class GateInApiManagementExtension implements ManagementExtension {
+ @Override
+ public void initialize(ExtensionContext context) {
+ context.registerManagedComponent(GateInApiManagementResource.class);
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
View
522 component/api/src/main/java/org/gatein/api/management/GateInApiManagementResource.java
@@ -0,0 +1,522 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api.management;
+
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.portal.mop.SiteKey;
+import org.exoplatform.web.WebAppController;
+import org.exoplatform.web.url.navigation.NavigationResource;
+import org.exoplatform.web.url.simple.SimpleURL;
+import org.exoplatform.web.url.simple.SimpleURLContext;
+import org.gatein.api.BasicPortalRequest;
+import org.gatein.api.EntityAlreadyExistsException;
+import org.gatein.api.EntityNotFoundException;
+import org.gatein.api.Portal;
+import org.gatein.api.PortalRequest;
+import org.gatein.api.Util;
+import org.gatein.api.common.Attributes;
+import org.gatein.api.common.URIResolver;
+import org.gatein.api.navigation.Navigation;
+import org.gatein.api.navigation.NodePath;
+import org.gatein.api.security.Group;
+import org.gatein.api.security.Permission;
+import org.gatein.api.security.User;
+import org.gatein.api.site.Site;
+import org.gatein.api.site.SiteId;
+import org.gatein.api.site.SiteQuery;
+import org.gatein.api.site.SiteType;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+import org.gatein.management.api.ManagedUser;
+import org.gatein.management.api.PathAddress;
+import org.gatein.management.api.annotations.Managed;
+import org.gatein.management.api.annotations.ManagedAfter;
+import org.gatein.management.api.annotations.ManagedBefore;
+import org.gatein.management.api.annotations.ManagedContext;
+import org.gatein.management.api.annotations.ManagedOperation;
+import org.gatein.management.api.annotations.ManagedRole;
+import org.gatein.management.api.annotations.MappedAttribute;
+import org.gatein.management.api.annotations.MappedPath;
+import org.gatein.management.api.exceptions.ResourceNotFoundException;
+import org.gatein.management.api.model.ModelList;
+import org.gatein.management.api.model.ModelObject;
+import org.gatein.management.api.model.ModelProvider;
+import org.gatein.management.api.model.ModelReference;
+import org.gatein.management.api.model.ModelString;
+import org.gatein.management.api.model.ModelValue;
+import org.gatein.management.api.operation.OperationContext;
+import org.gatein.management.api.operation.OperationNames;
+
+import java.util.List;
+import java.util.Locale;
+
+import static org.gatein.api.management.Utils.*;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+@SuppressWarnings("unused")
+@Managed(value = "api", description = "GateIn API Management Resource")
+public class GateInApiManagementResource {
+ private static final Logger log = LoggerFactory.getLogger("org.gatein.api.management");
+
+ private static final SiteQuery SITE_QUERY = new SiteQuery.Builder().withSiteTypes(SiteType.SITE).build();
+ private static final SiteQuery SPACE_QUERY = new SiteQuery.Builder().withSiteTypes(SiteType.SPACE).build();
+ private static final SiteQuery DASHBOARD_QUERY = new SiteQuery.Builder().withSiteTypes(SiteType.DASHBOARD).build();
+
+ private final Portal portal;
+
+ @ManagedContext
+ private final ModelProvider modelProvider; // gatein-management will set this field via reflection
+
+ public GateInApiManagementResource(Portal portal) {
+ this(portal, null);
+ }
+
+ // Constructor for testing to specify ModelProvider instead of gatein-management
+ GateInApiManagementResource(Portal portal, ModelProvider modelProvider) {
+ this.portal = portal;
+ this.modelProvider = modelProvider;
+ }
+
+ @ManagedBefore
+ public void before(@ManagedContext OperationContext context) {
+ PortalRequest portalRequest = PortalRequest.getInstance();
+ if (portalRequest == null) {
+ setCurrentPortalRequest(context);
+ }
+ }
+
+ @ManagedAfter
+ public void after() {
+ if (PortalRequest.getInstance() instanceof BasicPortalRequest) {
+ BasicPortalRequest.setInstance(null);
+ }
+ }
+
+ // ------------------------------------------------- Portal Sites --------------------------------------------------//
+ @Managed("/sites")
+ public ModelList getSites(@ManagedContext PathAddress address) {
+ return _getSites(SITE_QUERY, address);
+ }
+
+ @Managed("/sites/{site-name}")
+ public ModelObject getSite(@MappedPath("site-name") String siteName, @ManagedContext OperationContext context) {
+ SiteId id = new SiteId(siteName);
+ return _getSite(id, context);
+ }
+
+ @Managed("/sites/{site-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.ADD_RESOURCE, description = "Adds a given site")
+ public ModelObject addSite(@MappedPath("site-name") String siteName, @MappedAttribute("template") String template, @ManagedContext PathAddress address) {
+ SiteId siteId = new SiteId(siteName);
+ return _addSite(address, siteId, template);
+ }
+
+ @Managed("/sites/{site-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.REMOVE_RESOURCE, description = "Removes the given site")
+ public void removeSite(@MappedPath("site-name") String siteName) {
+ SiteId id = new SiteId(siteName);
+ _removeSite(id);
+ }
+
+ @Managed("/sites/{site-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.UPDATE_RESOURCE, description = "Updates a given site")
+ public ModelObject updateSite(@MappedPath("site-name") String siteName, @ManagedContext ModelObject siteModel, @ManagedContext PathAddress address) {
+ SiteId id = new SiteId(siteName);
+ return _updateSite(id, siteModel, address);
+ }
+
+ @Managed("/sites/{site-name}/pages")
+ public PageManagementResource getPages(@MappedPath("site-name") String siteName) {
+ SiteId id = new SiteId(siteName);
+ return pagesResource(id);
+ }
+
+ @Managed("/sites/{site-name}/navigation")
+ public NavigationManagementResource getNavigation(@MappedPath("site-name") String siteName) {
+ SiteId id = new SiteId(siteName);
+ return navigationResource(id);
+ }
+
+ // --------------------------------------------- Group Sites (Spaces) ----------------------------------------------//
+ @Managed("/spaces")
+ public ModelList getSpaces(@ManagedContext PathAddress address) {
+ return _getSites(SPACE_QUERY, address);
+ }
+
+ @Managed("/spaces/{group-name: .*}")
+ public ModelObject getSpace(@MappedPath("group-name") String groupName, @ManagedContext OperationContext context) {
+ SiteId id = new SiteId(new Group(groupName));
+ return _getSite(id, context);
+ }
+
+ @Managed("/spaces/{group-name: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.ADD_RESOURCE, description = "Adds a given site")
+ public ModelObject addSpace(@MappedPath("group-name") String groupName, @MappedAttribute("template") String template, @ManagedContext PathAddress address) {
+ SiteId siteId = new SiteId(new Group(groupName));
+ return _addSite(address, siteId, template);
+ }
+
+ @Managed("/spaces/{group-name: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.REMOVE_RESOURCE, description = "Removes the given space")
+ public void removeSpace(@MappedPath("group-name") String groupName) {
+ SiteId id = new SiteId(new Group(groupName));
+ _removeSite(id);
+ }
+
+ @Managed("/spaces/{group-name: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.UPDATE_RESOURCE, description = "Updates a given space")
+ public ModelObject updateSpace(@MappedPath("group-name") String groupName, @ManagedContext ModelObject siteModel, @ManagedContext PathAddress address) {
+ SiteId id = new SiteId(new Group(groupName));
+ return _updateSite(id, siteModel, address);
+ }
+
+ @Managed("/spaces/{group-name: .*}/pages")
+ public PageManagementResource getSpacePages(@MappedPath("group-name") String groupName) {
+ SiteId id = new SiteId(new Group(groupName));
+ return pagesResource(id);
+ }
+
+ @Managed("/spaces/{group-name: .*}/navigation")
+ public NavigationManagementResource getSpaceNavigation(@MappedPath("group-name") String groupName) {
+ SiteId id = new SiteId(new Group(groupName));
+ return navigationResource(id);
+ }
+
+ // -------------------------------------------- User Sites (Dashboard) ---------------------------------------------//
+ @Managed("/dashboards")
+ public ModelList getDashboards(@ManagedContext PathAddress address) {
+ return _getSites(DASHBOARD_QUERY, address);
+ }
+
+ @Managed("/dashboards/{user-name}")
+ public ModelObject getDashboard(@MappedPath("user-name") String userName, @ManagedContext OperationContext context) {
+ SiteId id = new SiteId(new User(userName));
+ return _getSite(id, context);
+ }
+
+ @Managed("/dashboards/{user-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.ADD_RESOURCE, description = "Adds a given site")
+ public ModelObject addDashboard(@MappedPath("user-name") String userName, @MappedAttribute("template") String template, @ManagedContext PathAddress address) {
+ SiteId siteId = new SiteId(new User(userName));
+ return _addSite(address, siteId, template);
+ }
+
+ @Managed("/dashboards/{user-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.REMOVE_RESOURCE, description = "Removes the given dashboard")
+ public void removeDashboard(@MappedPath("user-name") String userName) {
+ SiteId id = new SiteId(new User(userName));
+ _removeSite(id);
+ }
+
+ @Managed("/dashboards/{user-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.UPDATE_RESOURCE, description = "Updates a given space")
+ public ModelObject updateDashboard(@MappedPath("user-name") String userName, @ManagedContext ModelObject siteModel, @ManagedContext PathAddress address) {
+ SiteId id = new SiteId(new User(userName));
+ return _updateSite(id, siteModel, address);
+ }
+
+ @Managed("/dashboards/{user-name}/pages")
+ public PageManagementResource getDashboardPages(@MappedPath("user-name") String userName) {
+ SiteId id = new SiteId(new User(userName));
+ return pagesResource(id);
+ }
+
+ @Managed("/dashboards/{user-name}/navigation")
+ public NavigationManagementResource getDashboardNavigation(@MappedPath("user-name") String userName) {
+ SiteId id = new SiteId(new User(userName));
+ return navigationResource(id);
+ }
+
+ private NavigationManagementResource navigationResource(SiteId siteId) {
+ Navigation navigation = portal.getNavigation(siteId);
+ if (navigation == null) {
+ throw new ResourceNotFoundException("Navigation does not exist for site " + siteId);
+ }
+
+ return new NavigationManagementResource(navigation, modelProvider);
+ }
+
+ private PageManagementResource pagesResource(SiteId siteId) {
+ requireSite(siteId);
+ return new PageManagementResource(portal, modelProvider, siteId);
+ }
+
+ private ModelList _getSites(SiteQuery query, PathAddress address) {
+ List<Site> sites = portal.findSites(query);
+ ModelList list = modelProvider.newModel(ModelList.class);
+ populateModel(sites, list, address);
+
+ return list;
+ }
+
+ private ModelObject _getSite(SiteId id, OperationContext context) {
+ Site site = requireSite(id);
+
+ // Verify current user has access to site
+ verifyAccess(site, context);
+
+ // Populate site model
+ ModelObject siteModel = modelProvider.newModel(ModelObject.class);
+ populateModel(site, siteModel, context.getAddress());
+
+ return siteModel;
+ }
+
+ private ModelObject _addSite(PathAddress address, SiteId siteId, String template) {
+ Site site;
+ try {
+ if (template == null) {
+ site = portal.createSite(siteId);
+ } else {
+ site = portal.createSite(siteId, template);
+ }
+ } catch (EntityAlreadyExistsException e) {
+ throw alreadyExists("Could not add site", siteId);
+ }
+ portal.saveSite(site);
+
+ // Populate model
+ ModelObject siteModel = modelProvider.newModel(ModelObject.class);
+ populateModel(site, siteModel, address);
+
+ return siteModel;
+ }
+
+ private void _removeSite(SiteId id) {
+ requireSite(id);
+ try {
+ boolean removed = portal.removeSite(id);
+ if (!removed) throw new RuntimeException("Could not remove site + " + id + " for unknown reasons.");
+ } catch (EntityNotFoundException e) {
+ throw notFound("Cannot remove site", id);
+ }
+ }
+
+ private ModelObject _updateSite(SiteId id, ModelObject siteModel, PathAddress address) {
+ Site site = requireSite(id);
+
+ if (siteModel.has("displayName")) {
+ String displayName = get(siteModel, ModelString.class, "displayName").getValue();
+ site.setDisplayName(displayName);
+ }
+ if (siteModel.has("description")) {
+ String description = get(siteModel, ModelString.class, "description").getValue();
+ site.setDescription(description);
+ }
+ if (siteModel.has("skin")) {
+ String skin = get(siteModel, ModelString.class, "skin").getValue();
+ site.setSkin(skin);
+ }
+ if (siteModel.has("locale")) {
+ Locale locale = getLocale(siteModel, "locale");
+ site.setLocale(locale);
+ }
+ if (siteModel.has("access-permissions")) {
+ Permission permission = getPermission(siteModel, false, "access-permissions");
+ site.setAccessPermission(permission);
+ }
+ if (siteModel.has("edit-permissions")) {
+ Permission permission = getPermission(siteModel, true, "access-permissions");
+ site.setEditPermission(permission);
+ }
+ if (siteModel.hasDefined("attributes")) {
+ ModelList list = get(siteModel, ModelList.class, "attributes");
+ for (int i = 0; i < list.size(); i++) {
+ ModelValue mv = list.get(i);
+ String field = "attributes["+i+"]"; // Used for error reporting
+ if (mv.getValueType() != ModelValue.ModelValueType.OBJECT) {
+ throw invalidType(mv, ModelValue.ModelValueType.OBJECT, field);
+ }
+ ModelObject attrModel = mv.asValue(ModelObject.class);
+ if (!attrModel.hasDefined("key")) {
+ throw requiredField(field, "key");
+ }
+ String key = get(attrModel, ModelString.class, "key").getValue();
+ if (!attrModel.has("value")) {
+ throw requiredField(field, "value");
+ }
+ String value = get(attrModel, ModelString.class, "value").getValue();
+ site.getAttributes().put(key, value);
+ }
+ }
+
+ portal.saveSite(site);
+
+ ModelObject updatedSiteModel = modelProvider.newModel(ModelObject.class);
+ populateModel(site, updatedSiteModel, address);
+
+ return updatedSiteModel;
+ }
+
+ private Site requireSite(SiteId id) {
+ Site site = portal.getSite(id);
+ if (site == null) throw new ResourceNotFoundException("Site not found for " + id);
+
+ return site;
+ }
+
+ private void populateModel(Site site, ModelObject siteModel, PathAddress address) {
+ // Site fields
+ siteModel.set("name", site.getId().getName());
+ siteModel.set("type", site.getId().getType().name().toLowerCase());
+ siteModel.set("displayName", site.getDisplayName());
+ siteModel.set("description", site.getDescription());
+ siteModel.set("skin", site.getSkin());
+ populate("locale", site.getLocale(), siteModel);
+ populate("access-permissions", site.getAccessPermission(), siteModel);
+ populate("edit-permissions", site.getEditPermission(), siteModel);
+ ModelList attrList = siteModel.get("attributes", ModelList.class);
+ Attributes attributes = site.getAttributes();
+ for (String key : attributes.keySet()) {
+ ModelObject attr = attrList.add().setEmptyObject();
+ attr.set("key", key);
+ attr.set("value", attributes.get(key));
+ }
+
+ // Pages
+ ModelReference pagesRef = siteModel.get("pages", ModelReference.class);
+ pagesRef.set(address.append("pages"));
+
+ // Navigation
+ ModelReference navigationRef = siteModel.get("navigation", ModelReference.class);
+ navigationRef.set(address.append("navigation"));
+ }
+
+ private void populateModel(List<Site> sites, ModelList list, PathAddress address) {
+ for (Site site : sites) {
+ if (hasPermission(site.getAccessPermission())) {
+ ModelReference siteRef = list.add().asValue(ModelReference.class);
+ siteRef.set("name", site.getName());
+ siteRef.set("type", site.getType().getName());
+ siteRef.set(address.append(site.getName()));
+ }
+ }
+ }
+
+ private User getUser(ManagedUser managedUser) {
+ if (managedUser == null) return User.anonymous();
+
+ return new User(managedUser.getUserName());
+ }
+
+ private void setCurrentPortalRequest(OperationContext context) {
+ final ManagedUser managedUser = context.getUser();
+ final PathAddress address = context.getAddress();
+
+ // Retrieve siteId from address (can be null)
+ SiteId siteId = getSiteId(address);
+
+ // Retrieve nodePath from address (can be null)
+ NodePath nodePath = getNodePath(address);
+
+ Locale locale = context.getLocale();
+ // For some HTTP requests the locale is set to *, I guess to indicate a header 'Accept-Language: *' ?
+ if (locale != null && locale.getLanguage().equals("*")) {
+ locale = null;
+ }
+
+ User user = (managedUser == null || managedUser.getUserName() == null) ? User.anonymous() : new User(managedUser.getUserName());
+
+ final PortalContainer container = PortalContainer.getInstance();
+ final WebAppController controller = (WebAppController) container.getComponentInstanceOfType(WebAppController.class);
+ URIResolver uriResolver = new URIResolver() {
+ @Override
+ public String resolveURI(SiteId siteId) {
+ SiteKey siteKey = Util.from(siteId);
+ NavigationResource navResource = new NavigationResource(siteKey, "");
+ SimpleURL url = new SimpleURL(new SimpleURLContext(container, controller));
+ url.setSchemeUse(false);
+ url.setAuthorityUse(false);
+ String urlString = url.setResource(navResource).toString();
+ return urlString.substring(0, urlString.length() - 1);
+ }
+ };
+ BasicPortalRequest.setInstance(new BasicPortalRequest(user, siteId, nodePath, locale, portal, uriResolver));
+ }
+
+ private static SiteId getSiteId(PathAddress address) {
+ String siteName = address.resolvePathTemplate("site-name");
+ if (siteName != null) {
+ return new SiteId(siteName);
+ }
+
+ String groupName = address.resolvePathTemplate("group-name");
+ if (groupName != null) {
+ return new SiteId(new Group(groupName));
+ }
+
+ String userName = address.resolvePathTemplate("user-name");
+ if (userName != null) {
+ return new SiteId(new User(userName));
+ }
+
+ return null;
+ }
+
+ private static NodePath getNodePath(PathAddress address) {
+ String path = address.resolvePathTemplate("path");
+ if (path != null) {
+ return NodePath.fromString(path);
+ }
+
+ return null;
+ }
+
+ static PathAddress getSiteAddress(SiteId siteId) {
+ PathAddress address = PathAddress.pathAddress("api");
+ switch (siteId.getType()) {
+ case SITE:
+ address = address.append("sites");
+ break;
+ case SPACE:
+ address = address.append("spaces");
+ break;
+ case DASHBOARD:
+ address = address.append("dashboards");
+ break;
+ default:
+ throw new AssertionError();
+ }
+
+ return address.append(siteId.getName());
+ }
+
+ static PathAddress getPagesAddress(SiteId siteId) {
+ return getSiteAddress(siteId).append("pages");
+ }
+
+ static PathAddress getNavigationAddress(SiteId siteId) {
+ return getSiteAddress(siteId).append("navigation");
+ }
+}
View
428 component/api/src/main/java/org/gatein/api/management/NavigationManagementResource.java
@@ -0,0 +1,428 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api.management;
+
+import org.apache.commons.lang.LocaleUtils;
+import org.gatein.api.Portal;
+import org.gatein.api.common.i18n.LocalizedString;
+import org.gatein.api.navigation.Navigation;
+import org.gatein.api.navigation.Node;
+import org.gatein.api.navigation.NodePath;
+import org.gatein.api.navigation.NodeVisitor;
+import org.gatein.api.navigation.Nodes;
+import org.gatein.api.navigation.PublicationDate;
+import org.gatein.api.navigation.Visibility;
+import org.gatein.api.page.PageId;
+import org.gatein.api.site.SiteId;
+import org.gatein.api.site.SiteType;
+import org.gatein.management.api.PathAddress;
+import org.gatein.management.api.annotations.Managed;
+import org.gatein.management.api.annotations.ManagedContext;
+import org.gatein.management.api.annotations.ManagedOperation;
+import org.gatein.management.api.annotations.ManagedRole;
+import org.gatein.management.api.annotations.MappedAttribute;
+import org.gatein.management.api.annotations.MappedPath;
+import org.gatein.management.api.exceptions.OperationException;
+import org.gatein.management.api.exceptions.ResourceNotFoundException;
+import org.gatein.management.api.model.Model;
+import org.gatein.management.api.model.ModelList;
+import org.gatein.management.api.model.ModelObject;
+import org.gatein.management.api.model.ModelProvider;
+import org.gatein.management.api.model.ModelReference;
+import org.gatein.management.api.model.ModelString;
+import org.gatein.management.api.model.ModelValue;
+import org.gatein.management.api.operation.OperationContext;
+import org.gatein.management.api.operation.OperationNames;
+
+import java.util.Date;
+import java.util.Locale;
+
+import static org.gatein.api.management.GateInApiManagementResource.*;
+import static org.gatein.api.management.Utils.*;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+@Managed
+@SuppressWarnings("unused")
+public class NavigationManagementResource {
+ private final Navigation navigation;
+ private final ModelProvider modelProvider;
+
+ public NavigationManagementResource(Navigation navigation, ModelProvider modelProvider) {
+ this.navigation = navigation;
+ this.modelProvider = modelProvider;
+ }
+
+ @Managed
+ public ModelObject getNavigation(@ManagedContext OperationContext context,
+ @MappedAttribute("scope") String scopeAttribute,
+ @MappedAttribute("showAll") String showAllAttribute) {
+ // Populate the model
+ ModelObject model = modelProvider.newModel(ModelObject.class);
+
+ NodeVisitor visitor = Nodes.visitChildren();
+ int scope = 0;
+ if (scopeAttribute != null) {
+ scope = Integer.parseInt(scopeAttribute);
+ visitor = Nodes.visitNodes(scope);
+ }
+
+ Node node = getNode(NodePath.root(), true, visitor);
+ boolean showAll = showAllAttribute != null && Boolean.parseBoolean(showAllAttribute);
+ if (!showAll || !context.getExternalContext().isUserInRole("administrators")) {
+ node = node.filter().showDefault();
+ }
+
+ populateNavigationModel(node, scope, model, context);
+
+ return model;
+ }
+
+ @Managed("{path: .*}")
+ public ModelObject getNode(@MappedPath("path") String path, @MappedAttribute("scope") String scopeAttribute,
+ @MappedAttribute("showAll") String showAllAttribute, @ManagedContext OperationContext context) {
+ NodeVisitor visitor = Nodes.visitChildren();
+ int scope = 0;
+ if (scopeAttribute != null) {
+ scope = Integer.parseInt(scopeAttribute);
+ visitor = Nodes.visitNodes(scope);
+ }
+ Node node = getNode(path, true, visitor);
+ boolean showAll = showAllAttribute != null && Boolean.parseBoolean(showAllAttribute);
+ if (showAll && context.getExternalContext().isUserInRole("administrators")) {
+ node = node.filter().showDefault();
+ } else {
+ node = node.filter().showDefault();
+ }
+
+ // Populate the model
+ ModelObject model = modelProvider.newModel(ModelObject.class);
+ populateNode(node, scope, model, context.getAddress());
+
+ return model;
+ }
+
+ @Managed("{path: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.REMOVE_RESOURCE, description = "Removes the navigation node")
+ public void removeNode(@MappedPath("path") String path) {
+ Node node = getNode(path, true);
+
+ Node parent = node.getParent();
+ parent.removeChild(node.getName());
+ navigation.saveNode(parent);
+ }
+
+ @Managed("{path: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.ADD_RESOURCE, description = "Adds the navigation node")
+ public ModelObject addNode(@MappedPath("path") String path, @ManagedContext PathAddress address) {
+ NodePath nodePath = NodePath.fromString(path);
+ Node parent = getNode(nodePath.parent(), true, Nodes.visitChildren());
+ String name = nodePath.getLastSegment();
+
+ if (parent.hasChild(name)) {
+ throw new OperationException(OperationNames.ADD_RESOURCE, "Node already exists for " + nodePath);
+ }
+
+ // Add child and save
+ Node child = parent.addChild(name);
+ navigation.saveNode(parent);
+
+ // Populate model
+ ModelObject model = modelProvider.newModel(ModelObject.class);
+ populateNode(child, 0, model, address);
+
+ return model;
+ }
+
+ @Managed("{path: .*}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.UPDATE_RESOURCE, description = "Updates the navigation node")
+ public ModelObject updateNode(@MappedPath("path") String path, @ManagedContext ModelObject nodeModel, @ManagedContext PathAddress address) {
+
+ // Update node from model
+ Node node = getNode(path, true);
+ updateNodeFromModel(node, nodeModel);
+
+ // Save node
+ navigation.saveNode(node);
+
+ // Populate model for update node
+ ModelObject updateNodeModel = modelProvider.newModel(ModelObject.class);
+ populateNode(node, 0, updateNodeModel, address);
+
+ return updateNodeModel;
+ }
+
+ private Node getNode(String pathString, boolean require) {
+ return getNode(pathString, require, Nodes.visitNone());
+ }
+
+ private Node getNode(String pathString, boolean require, NodeVisitor visitor) {
+ return getNode(NodePath.fromString(pathString), require, visitor);
+ }
+
+ private Node getNode(NodePath path, boolean require) {
+ return getNode(path, require, Nodes.visitNone());
+ }
+
+ private Node getNode(NodePath path, boolean require, NodeVisitor visitor) {
+ Node node = navigation.getNode(path, visitor);
+ if (node == null && require)
+ throw notFound("Cannot retrieve node", navigation.getSiteId(), path);
+
+ return node;
+ }
+
+ private void populateNavigationModel(Node rootNode, int scope, ModelObject model, OperationContext context) {
+ PathAddress address = context.getAddress();
+
+ // Populate navigation fields
+ model.set("priority", navigation.getPriority());
+ model.set("siteType", navigation.getSiteId().getType().getName());
+ model.set("siteName", navigation.getSiteId().getName());
+ ModelList nodesModel = model.get("nodes").setEmptyList();
+ if (rootNode.isChildrenLoaded()) {
+ for (Node child : rootNode) {
+ Model childModel = nodesModel.add();
+ PathAddress childAddress = address.append(child.getName());
+ if (scope > 0 || scope < 0) // Continue populating nodes in response
+ {
+ populateNode(child, scope - 1, childModel.setEmptyObject(), childAddress);
+ } else { // Populate node reference which can be followed
+ ModelReference nodeRef = childModel.set(childAddress);
+ nodeRef.set("name", child.getName());
+ }
+ }
+ }
+ }
+
+ private void populateNode(Node node, int scope, ModelObject model, PathAddress address) {
+ model.set("name", node.getName());
+ set("uri", node.getURI(), model);
+ model.set("isVisible", node.isVisible());
+ populateVisibility(node.getVisibility(), model.get("visibility", ModelObject.class));
+ model.set("iconName", node.getIconName());
+
+ // Display name
+ model.set("displayName", node.getDisplayName());
+ populate("displayNames", node.getDisplayNames(), model);
+
+ // Children nodes
+ ModelList children = model.get("children", ModelList.class);
+ if (node.isChildrenLoaded()) {
+ for (Node child : node) {
+ Model childModel = children.add();
+ PathAddress childAddress = address.append(child.getName());
+ if (scope > 0 || scope < 0) // Continue populating nodes in response
+ {
+ populateNode(child, scope - 1, childModel.setEmptyObject(), childAddress);
+ } else { // Populate node reference which can be followed
+ ModelReference nodeRef = childModel.set(childAddress);
+ nodeRef.set("name", child.getName());
+ }
+ }
+ }
+ // Page reference
+ ModelReference pageRef = model.get("page").asValue(ModelReference.class);
+ if (node.getPageId() != null) {
+ PageId pageId = node.getPageId();
+ pageRef.set("pageName", pageId.getPageName());
+ pageRef.set("siteName", pageId.getSiteId().getName());
+ pageRef.set("siteType", pageId.getSiteId().getType().getName());
+
+ // Set the address for the ref
+ PathAddress pageAddress = getPagesAddress(pageId.getSiteId()).append(pageId.getPageName());
+ pageRef.set(pageAddress);
+ }
+ }
+
+ private void populateVisibility(Visibility visibility, ModelObject model) {
+ if (visibility != null) {
+ set("status", visibility.getStatus(), model);
+ if (visibility.getPublicationDate() != null) {
+ ModelObject pubDateModel = model.get("publication-date", ModelObject.class);
+ Date start = visibility.getPublicationDate().getStart();
+ Date end = visibility.getPublicationDate().getEnd();
+ set("start", start, pubDateModel);
+ set("end", end, pubDateModel);
+ }
+ }
+ }
+
+ private void updateNodeFromModel(Node node, ModelObject nodeModel) {
+
+ // Update name
+ if (nodeModel.has("name")) {
+ node.setName(nonNullString(nodeModel, "name"));
+ }
+
+ // Update visibility
+ if (nodeModel.has("visibility")) {
+ Visibility visibility = getVisibility(nodeModel, node.getVisibility());
+ if (visibility != null) {
+ node.setVisibility(visibility);
+ }
+ }
+
+ // Update iconName
+ if (nodeModel.has("iconName")) {
+ String iconName = get(nodeModel, ModelString.class, "iconName").getValue();
+ node.setIconName(iconName);
+ }
+
+ // Update pageId
+ if (nodeModel.has("page")) {
+ node.setPageId(getPageId(nodeModel));
+ }
+
+ //TODO: Support adding and not just overwriting. i.e. one locale/value pair is added to rest.
+ // Update displayName(s)
+ if (nodeModel.has("displayName")) {
+ if (nodeModel.has("displayNames")) {
+ throw invalidData("Cannot define both displayName and displayNames");
+ }
+ String displayName = get(nodeModel, ModelString.class, "displayName").getValue();
+ node.setDisplayName(displayName);
+ } else if (nodeModel.has("displayNames")) {
+ LocalizedString displayName = getDisplayNames(nodeModel);
+ node.setDisplayNames(displayName);
+ }
+ }
+
+ private static LocalizedString getDisplayNames(ModelObject nodeModel) {
+ ModelList list = get(nodeModel, ModelList.class, "displayNames");
+ if (!list.isDefined()) {
+ throw invalidValue(null, "displayNames");
+ }
+ LocalizedString displayName = null;
+ int i=0;
+ for (ModelValue mv : list) {
+ ModelObject displayNameModel = mv.asValue(ModelObject.class);
+
+ // Parse value (required && non-null)
+ if (!displayNameModel.has("value")) {
+ throw requiredField("displayNames["+i+"].value");
+ }
+ String value = get(displayNameModel, ModelString.class, "value").getValue();
+ if (value == null) {
+ throw invalidValue(value, "displayNames[" + i + "].value");
+ }
+
+ // Parse lang (not-required but if defined must be non-null)
+ if (displayNameModel.has("lang")) {
+ ModelString langModel = get(displayNameModel, ModelString.class, "lang");
+ String lang = langModel.getValue();
+ if (lang == null) {
+ // Have to hard code the field for now to support array
+ throw invalidValue(lang, "displayNames[" + i + "].lang");
+ }
+ Locale locale;
+ try {
+ locale = LocaleUtils.toLocale(lang);
+ } catch (IllegalArgumentException e) {
+ throw invalidValue(lang, "displayNames["+i+"].lang");
+ }
+ if (displayName == null) {
+ displayName = new LocalizedString(locale, value);
+ } else {
+ displayName.setLocalizedValue(locale, value);
+ }
+ } else if (displayName == null) {
+ displayName = new LocalizedString(value);
+ } else {
+ throw invalidData("Cannot have multiple non localized values for displayNames");
+ }
+ }
+
+ return displayName;
+ }
+
+ private static PageId getPageId(ModelObject nodeModel) {
+ ModelObject pageModel = get(nodeModel, ModelObject.class, "page");
+ if (pageModel.isDefined()) {
+ String pageName = nonNullString(nodeModel, "page", "pageName");
+ String siteName = nonNullString(nodeModel, "page", "siteName");
+ String siteTypeString = nonNullString(nodeModel, "page", "siteType");
+ SiteType siteType = SiteType.forName(siteTypeString);
+ if (siteType == null) {
+ throw invalidValue(siteTypeString, "page", "siteType");
+ }
+ return new PageId(new SiteId(siteType, siteName), pageName);
+ } else {
+ return null;
+ }
+ }
+
+ private static Visibility getVisibility(ModelObject nodeModel, Visibility original) {
+ Visibility.Status status = getStatus(nodeModel);
+ if (status == Visibility.Status.PUBLICATION) {
+ ModelObject pubDateModel = get(nodeModel, ModelObject.class, "visibility", "publication-date");
+ // If status was set to PUBLICATION however no publication date was specified then throw exception
+ if (!pubDateModel.isDefined()) {
+ throw requiredFieldWhen("visibility status is " + status, "visibility", "publication-date");
+ }
+ PublicationDate publicationDate = getPublicationDate(nodeModel, original.getPublicationDate());
+ return new Visibility(publicationDate);
+ } else {
+ return new Visibility(status);
+ }
+ }
+
+ private static Visibility.Status getStatus(ModelObject nodeModel) {
+ String statusString = nonNullString(nodeModel, "visibility", "status");
+ Visibility.Status status;
+ try {
+ status = Visibility.Status.valueOf(statusString.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw invalidValue(statusString, "visibility", "status");
+ }
+ return status;
+ }
+
+ private static PublicationDate getPublicationDate(ModelObject nodeModel, PublicationDate previous) {
+ ModelString startModel = get(nodeModel, ModelString.class, "visibility", "publication-date", "start");
+ Date start = (previous == null) ? null : previous.getStart();
+ if (startModel.isDefined()) {
+ start = getDate(nodeModel, "visibility", "publication-date", "start");
+ }
+
+ ModelString endModel = get(nodeModel, ModelString.class, "visibility", "publication-date", "end");
+ Date end = (previous == null) ? null : previous.getEnd();
+ if (endModel.isDefined()) {
+ end = getDate(nodeModel, "visibility", "publication-date", "end");
+ }
+
+ if (start != null && end != null) {
+ return PublicationDate.between(start, end);
+ } else if (start == null && end != null) {
+ return PublicationDate.endingOn(end);
+ } else if (start != null) {
+ return PublicationDate.startingOn(start);
+ } else {
+ throw invalidData("Either 'start' or 'end' is required for visibility.publication-date");
+ }
+ }
+}
View
151 component/api/src/main/java/org/gatein/api/management/PageManagementResource.java
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.gatein.api.management;
+
+import org.gatein.api.EntityAlreadyExistsException;
+import org.gatein.api.EntityNotFoundException;
+import org.gatein.api.Portal;
+import org.gatein.api.page.Page;
+import org.gatein.api.page.PageId;
+import org.gatein.api.page.PageQuery;
+import org.gatein.api.site.SiteId;
+import org.gatein.management.api.PathAddress;
+import org.gatein.management.api.annotations.Managed;
+import org.gatein.management.api.annotations.ManagedContext;
+import org.gatein.management.api.annotations.ManagedOperation;
+import org.gatein.management.api.annotations.ManagedRole;
+import org.gatein.management.api.annotations.MappedAttribute;
+import org.gatein.management.api.annotations.MappedPath;
+import org.gatein.management.api.model.ModelList;
+import org.gatein.management.api.model.ModelObject;
+import org.gatein.management.api.model.ModelProvider;
+import org.gatein.management.api.model.ModelReference;
+import org.gatein.management.api.operation.OperationNames;
+
+import java.util.List;
+
+import static org.gatein.api.management.Utils.*;
+
+/**
+ * @author <a href="mailto:nscavell@redhat.com">Nick Scavelli</a>
+ */
+@Managed
+@SuppressWarnings("unused")
+public class PageManagementResource {
+ private final Portal portal;
+ private final ModelProvider modelProvider;
+ private final SiteId siteId;
+
+ public PageManagementResource(Portal portal, ModelProvider modelProvider, SiteId siteId) {
+ this.portal = portal;
+ this.modelProvider = modelProvider;
+ this.siteId = siteId;
+ }
+
+ @Managed(description = "Retrieves all pages for given site")
+ public ModelList getPages(@ManagedContext PathAddress address) {
+ // Populate model
+ ModelList list = modelProvider.newModel(ModelList.class);
+ populateModel(portal.findPages(new PageQuery.Builder().withSiteId(siteId).build()), list, address);
+
+ return list;
+ }
+
+ @Managed("{page-name}")
+ public ModelObject getPage(@MappedPath("page-name") String name) {
+ PageId pageId = new PageId(siteId, name);
+ Page page = portal.getPage(pageId);
+ if (page == null) {
+ throw notFound("Could not retrieve page", pageId);
+ }
+
+ // Populate model
+ ModelObject model = modelProvider.newModel(ModelObject.class);
+ populateModel(page, model);
+
+ return model;
+ }
+
+ @Managed("{page-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.REMOVE_RESOURCE, description = "Removes the given page from the portal")
+ public void removePage(@MappedPath("page-name") String name) {
+ PageId pageId = new PageId(siteId, name);
+ try {
+ if (!portal.removePage(pageId)) {
+ throw notFound("Could not remove page", pageId);
+ }
+ } catch (EntityNotFoundException e) {
+ throw notFound("Could not remove page", siteId);
+ }
+ }
+
+ @Managed("{page-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.ADD_RESOURCE, description = "Adds the given page to the portal")
+ public ModelObject addPage(@MappedPath("page-name") String name, @MappedAttribute("displayName") String displayName) {
+
+ PageId pageId = new PageId(siteId, name);
+ Page page;
+ try {
+ page = portal.createPage(pageId);
+ } catch (EntityAlreadyExistsException e) {
+ throw alreadyExists("Could not add page", pageId);
+ } catch (EntityNotFoundException e) {
+ throw alreadyExists("Cannot add page", siteId);
+ }
+ page.setDisplayName(displayName);
+ portal.savePage(page);
+
+ ModelObject model = modelProvider.newModel(ModelObject.class);
+ populateModel(page, model);
+
+ return model;
+ }
+
+ @Managed("{page-name}")
+ @ManagedRole("administrators")
+ @ManagedOperation(name = OperationNames.UPDATE_RESOURCE, description = "Updates a page of the portal")
+ public ModelObject addPage(@MappedPath("page-name") String name, @ManagedContext ModelObject pageModel) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void populateModel(List<Page> pages, ModelList list, PathAddress address) {
+ for (Page page : pages) {
+ if (Utils.hasPermission(page.getAccessPermission())) {
+ ModelReference pageRef = list.add().asValue(ModelReference.class);
+ pageRef.set("name", page.getName());
+ pageRef.set("siteType", page.getId().getSiteId().getType().name().toLowerCase());
+ pageRef.set("siteName", page.getId().getSiteId().getName());
+ pageRef.set(address.append(page.getName()));
+ }
+ }
+ }
+