diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 679edbafb0..7d6c8e76b4 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -791,6 +791,11 @@ create_website_step1_title=Step One - Website Details create_website_step1_desc=Enter the information about the website. create_website_finish_instruction=To close this wizard and create your website space click Finish. To review or change your selections click Back. +# Browse Website and Sandboxes messages +title_browse_website=Browse Website Sandboxes +website_info=Use this view to browse the staging area and user sandboxes for a website. +staging_sandbox=Staging Sandbox + # New User Wizard messages new_user_title=New User Wizard new_user_title_edit=Edit User Wizard diff --git a/config/alfresco/web-client-config-navigation.xml b/config/alfresco/web-client-config-navigation.xml index 0dab5a7ec2..f25b0fc8c5 100644 --- a/config/alfresco/web-client-config-navigation.xml +++ b/config/alfresco/web-client-config-navigation.xml @@ -42,4 +42,12 @@ + + + + + + + + diff --git a/source/java/org/alfresco/web/bean/wcm/AVMConstants.java b/source/java/org/alfresco/web/bean/wcm/AVMConstants.java index 60239d629d..2ddea36465 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMConstants.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMConstants.java @@ -19,7 +19,7 @@ package org.alfresco.web.bean.wcm; /** * @author Kevin Roast */ -public class AVMConstants +public final class AVMConstants { /** * Private constructor @@ -28,10 +28,22 @@ public class AVMConstants { } + // names of the stores representing the layers for an AVM website public final static String STORE_STAGING = "-staging"; public final static String STORE_MAIN = "-main"; public final static String STORE_PREVIEW = "-preview"; + // system directories at the top level of an AVM website public final static String DIR_APPBASE = "appBase"; public final static String DIR_WEBAPPS = "avm_webapps"; + + // system property keys for sandbox identification and DNS virtualisation mapping + public final static String PROP_SANDBOXID = ".sandbox-id."; + public final static String PROP_SANDBOX_STAGING_MAIN = ".sandbox.staging.main"; + public final static String PROP_SANDBOX_STAGING_PREVIEW = ".sandbox.staging.preview"; + public final static String PROP_SANDBOX_AUTHOR_MAIN = ".sandbox.author.main"; + public final static String PROP_SANDBOX_AUTHOR_PREVIEW = ".sandbox.author.preview"; + public final static String PROP_DNS = ".dns."; + + public final static String SPACE_ICON_WEBSITE = "space-icon-website"; } diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java index af0f1b7df2..a7ae2a90fe 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java @@ -26,15 +26,16 @@ import javax.faces.context.FacesContext; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.bean.spaces.CreateSpaceWizard; import org.alfresco.web.bean.wizard.BaseWizardBean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -89,22 +90,22 @@ public class CreateWebsiteWizard extends BaseWizardBean // apply the uifacets aspect - icon, title and description props Map uiFacetsProps = new HashMap(4); - uiFacetsProps.put(ContentModel.PROP_ICON, CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME); + uiFacetsProps.put(ContentModel.PROP_ICON, AVMConstants.SPACE_ICON_WEBSITE); uiFacetsProps.put(ContentModel.PROP_TITLE, this.title); uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, this.description); this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps); - // TODO: create layers for invited users // TODO: invite users with appropriate permissions into this folder - // create the AVM store to represent the newly created location website - this.avmService.createAVMStore(this.name); - AVMStoreDescriptor avmStore = this.avmService.getAVMStore(this.name); - this.avmService.createDirectory("/", "appBase"); - this.avmService.createDirectory("/appBase", "avm_webapps"); - this.avmService.createDirectory("/appBase/avm_webapps", this.name); + // create the AVM stores (layers) to represent the newly created location website + createStagingSandbox(this.name); + // create layer for current user (TODO: based on role) + createUserSandbox(this.name, Application.getCurrentUser(context).getUserName()); + // TODO: create layers for invited users based on roles + + // TODO: import the ZIP structure into the AVM staging store // set the property on the node to reference the AVM store this.nodeService.setProperty(nodeRef, ContentModel.PROP_AVMSTORE, this.name); @@ -216,26 +217,149 @@ public class CreateWebsiteWizard extends BaseWizardBean return this.websitesFolderId; } - private void createStagingStore(String name) + /** + * Create the staging sandbox for the named store. + * + * A staging sandbox is comprised of two stores, the first named 'storename-staging' with a + * preview store named 'storename-preview' layered over the staging store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.staging.main and .sandbox.staging.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * + * @param name The store name to create the sandbox for + */ + private void createStagingSandbox(String name) { + // create the 'staging' store for the website String stagingStore = name + AVMConstants.STORE_STAGING; this.avmService.createAVMStore(stagingStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + stagingStore); + + // create the system directories 'appBase' and 'avm_webapps' String path = stagingStore + ":/"; this.avmService.createDirectory(path, AVMConstants.DIR_APPBASE); - path += '/' + AVMConstants.DIR_APPBASE; + path += AVMConstants.DIR_APPBASE; this.avmService.createDirectory(path, AVMConstants.DIR_WEBAPPS); - } - - private void createSandboxStores(String name, String username) - { - String sandboxStore = name + '-' + username + AVMConstants.STORE_MAIN; - this.avmService.createAVMStore(sandboxStore); - String path = sandboxStore + ":/"; - this.avmService.createLayeredDirectory(name + AVMConstants.STORE_STAGING, path, AVMConstants.DIR_APPBASE); + // tag the store with the store type + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_STAGING_MAIN), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(stagingStore); + + + // create the 'preview' store for the website String previewStore = name + AVMConstants.STORE_PREVIEW; this.avmService.createAVMStore(previewStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + previewStore); + + // create a layered directory pointing to 'appBase' in the staging area path = previewStore + ":/"; - this.avmService.createLayeredDirectory(name + AVMConstants.STORE_STAGING, path, AVMConstants.DIR_APPBASE); + String targetPath = name + AVMConstants.STORE_STAGING + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_STAGING_PREVIEW), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(previewStore); + + + // tag all related stores to indicate that they are part of a single sandbox + String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + this.avmService.setStoreProperty(previewStore, + QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + } + + /** + * Create a user sandbox for the named store. + * + * A user sandbox is comprised of two stores, the first named 'storename-username-main' layered + * over the staging store with a preview store named 'storename-username-preview' layered over + * the main store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.author.main and .sandbox.author.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * + * @param name The store name to create the sandbox for + * @param username Username of the user to create the sandbox for + */ + private void createUserSandbox(String name, String username) + { + // create the user 'main' store + String userStore = name + '-' + username + AVMConstants.STORE_MAIN; + this.avmService.createAVMStore(userStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + userStore); + + // create a layered directory pointing to 'appBase' in the staging area + String path = userStore + ":/"; + String targetPath = name + AVMConstants.STORE_STAGING + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(userStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_AUTHOR_MAIN), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(userStore); + + + // create the user 'preview' store + String previewStore = name + '-' + username + AVMConstants.STORE_PREVIEW; + this.avmService.createAVMStore(previewStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + previewStore); + + // create a layered directory pointing to 'appBase' in the user 'main' store + path = previewStore + ":/"; + targetPath = userStore + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(previewStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_AUTHOR_PREVIEW), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(previewStore); + + + // tag all related stores to indicate that they are part of a single sandbox + String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); + this.avmService.setStoreProperty(userStore, QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + this.avmService.setStoreProperty(previewStore, QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + } + + /** + * Tag a named store with a DNS path meta-data attribute. + * The DNS meta-data attribute is set to the system path 'store:/appBase/avm_webapps' + * + * @param store Name of the store to tag + */ + private void tagStoreDNSPath(String store) + { + String path = store + ":/" + AVMConstants.DIR_APPBASE + '/' + AVMConstants.DIR_WEBAPPS; + // TODO: DNS name mangle the property name - can only contain value DNS characters! + String dnsProp = AVMConstants.PROP_DNS + store; + this.avmService.setStoreProperty(store, QName.createQName(null, dnsProp), + new PropertyValue(DataTypeDefinition.TEXT, path)); } } diff --git a/source/web/images/icons/sandbox.gif b/source/web/images/icons/sandbox.gif new file mode 100644 index 0000000000..0a55432118 Binary files /dev/null and b/source/web/images/icons/sandbox.gif differ diff --git a/source/web/images/icons/sandbox_large.gif b/source/web/images/icons/sandbox_large.gif new file mode 100644 index 0000000000..1d1c87eb73 Binary files /dev/null and b/source/web/images/icons/sandbox_large.gif differ diff --git a/source/web/images/icons/space-icon-website-16.gif b/source/web/images/icons/space-icon-website-16.gif new file mode 100644 index 0000000000..0a55432118 Binary files /dev/null and b/source/web/images/icons/space-icon-website-16.gif differ diff --git a/source/web/images/icons/space-icon-website.gif b/source/web/images/icons/space-icon-website.gif new file mode 100644 index 0000000000..1d1c87eb73 Binary files /dev/null and b/source/web/images/icons/space-icon-website.gif differ diff --git a/source/web/jsp/wcm/browse-website.jsp b/source/web/jsp/wcm/browse-website.jsp new file mode 100644 index 0000000000..0e81fe992e --- /dev/null +++ b/source/web/jsp/wcm/browse-website.jsp @@ -0,0 +1,147 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> + +<%@ 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="64kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details - Staging sandbox --%> + + + + + + + <%-- Details - User sandboxes --%> + + + + + + + <%-- Error Messages --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + +
+ + <%-- Summary --%> +
+
+
+
+ +
+ + + <%-- Staging Sandbox Info here --%> + ---STAGING SANDBOX INFO HERE--- + + + +
+ + + + <%-- User Sandboxes List --%> + ---USER SANDBOXES HERE--- + + + +
+ <%-- messages tag to show messages not handled by other specific message tags --%> + +
+
+ +
+ +
+ +