/* * Copyright 2015 Time Warner Cable, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.twcable.jackalope.impl.cq; import com.day.cq.commons.jcr.JcrUtil; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import com.day.cq.wcm.api.Revision; import com.day.cq.wcm.api.Template; import com.day.cq.wcm.api.WCMException; import com.day.cq.wcm.api.msm.Blueprint; import com.google.common.collect.Lists; import com.twcable.jackalope.JcrConstants; import com.twcable.jackalope.impl.common.Paths; import com.twcable.jackalope.impl.jcr.ValueImpl; import com.twcable.jackalope.impl.sling.NodeResourceImpl; import org.apache.jackrabbit.commons.JcrUtils; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ValueMap; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import java.util.Calendar; import java.util.Collection; /** * Page Manager implementation. */ public class PageManagerImpl implements PageManager { private final ResourceResolver resolver; private final Session session; public PageManagerImpl(ResourceResolver resolver) { this.resolver = resolver; Session session = resolver.adaptTo(Session.class); if (session == null) throw new IllegalArgumentException("Resolver must be adaptable to Session."); this.session = session; } @Override public Page getPage(String path) { Resource resource = resolver.getResource(path); return resource != null ? resource.adaptTo(Page.class) : null; } @Override public Page getContainingPage(Resource resource) { if (resource == null) return null; String path = resource.getPath(); while (!Paths.isRoot(path)) { Page page = getPage(path); if (page != null) return page; path = path.substring(0, path.lastIndexOf("/")); } return null; } @Override public Page getContainingPage(String path) { return getContainingPage(resolver.getResource(path)); } @Override public Page create(String parentPath, String pageName, String template, String title) throws WCMException { return create(parentPath, pageName, template, title, true); } @Override public Page create(String parentPath, String pageName, String template, String title, boolean autoSave) throws WCMException { if (parentPath == null) throw new IllegalArgumentException("Parent path can't be null."); if (pageName == null && title == null) throw new IllegalArgumentException("Page and title name can't be both null."); if (template != null && !template.isEmpty()) throw new UnsupportedOperationException("Templates are not supported."); try { Node parent = JcrUtils.getOrCreateByPath(parentPath, JcrConstants.NT_UNSTRUCTURED, session); if (pageName == null || pageName.isEmpty()) pageName = JcrUtil.createValidName(title, JcrUtil.HYPHEN_LABEL_CHAR_MAPPING); if (!JcrUtil.isValidName(pageName)) throw new IllegalArgumentException("Illegal page name: " + pageName); Node pageNode = parent.addNode(pageName, JcrConstants.CQ_PAGE); Node contentNode = pageNode.addNode("jcr:content", JcrConstants.CQ_PAGE_CONTENT); if (title != null && !title.isEmpty()) contentNode.setProperty("jcr:title", title); if (autoSave) { session.save(); } return getPage(pageNode.getPath()); } catch (RepositoryException e) { throw new WCMException("Unable to create page", e); } } @Override public Page move(Page page, String destination, String beforeName, boolean shallow, boolean resolveConflicts, String[] adjustRefs) throws WCMException { throw new UnsupportedOperationException(); } @Override public Resource move(Resource resource, String destination, String beforeName, boolean shallow, boolean resolveConflicts, String[] adjustRefs) throws WCMException { throw new UnsupportedOperationException(); } @Override public Page copy(Page page, String destination, String beforeName, boolean shallow, boolean resolveConflict) throws WCMException { return copy(page, destination, beforeName, shallow, resolveConflict, false); } @Override public Page copy(Page page, String destination, String beforeName, boolean shallow, boolean resolveConflict, boolean autoSave) throws WCMException { if (beforeName != null && !beforeName.isEmpty()) throw new UnsupportedOperationException("Ordering not supported."); if (resolveConflict) throw new UnsupportedOperationException("Conflict resolution not supported."); if (!shallow) throw new UnsupportedOperationException("Recursive page copy not supported."); Page newPage = null; try { newPage = create(destination, page.getName(), null, page.getTitle()); Resource contentResource = newPage.getContentResource(); if (contentResource == null) throw new WCMException("Content resource is null."); Node contentNode = contentResource.adaptTo(Node.class); ValueMap properties = newPage.getProperties(); if (contentNode != null && properties != null) for (String key : properties.keySet()) contentNode.setProperty(key, new ValueImpl(properties.get(key))); else throw new WCMException("Unable to copy properties"); for (Resource child : Lists.newArrayList(page.getContentResource().listChildren())) { copy(child, contentResource.getPath() + "/" + child.getName(), null, false, false, false); } if (autoSave) session.save(); return newPage; } catch (RepositoryException e) { delete(newPage, false); throw new WCMException("Unable to copy properties.", e); } catch (WCMException e) { delete(newPage, false); throw e; } } @Override public Resource copy(Resource resource, String destination, String beforeName, boolean shallow, boolean resolveConflict) throws WCMException { return copy(resource, destination, beforeName, shallow, resolveConflict, false); } @Override public Resource copy(Resource resource, String destination, String beforeName, boolean shallow, boolean resolveConflict, boolean autoSave) throws WCMException { if (beforeName != null && !beforeName.isEmpty()) throw new UnsupportedOperationException("Ordering not supported."); if (resolveConflict) throw new UnsupportedOperationException("Conflict resolution not supported."); try { int index = destination.lastIndexOf("/"); String parentPath = destination.substring(0, index); String name = destination.substring(index + 1); Node parent = JcrUtils.getOrCreateByPath(parentPath, JcrConstants.NT_UNSTRUCTURED, session); Node node = resource.adaptTo(Node.class); if (node == null) throw new WCMException("Unable to get source node."); if (node.hasNode(name)) throw new WCMException("Node already exists at destination."); Node newNode = parent.addNode(name, node.getPrimaryNodeType().toString()); ValueMap properties = resource.adaptTo(ValueMap.class); for (String key : properties.keySet()) newNode.setProperty(key, new ValueImpl(properties.get(key))); if (!shallow && node.hasNodes()) for (Resource child : Lists.newArrayList(resource.listChildren())) copy(child, resource.getPath() + "/" + child.getName(), null, false, false, false); if (autoSave) session.save(); return new NodeResourceImpl(resolver, newNode); } catch (RepositoryException e) { try { if (session.itemExists(destination)) session.removeItem(destination); } catch (RepositoryException e1) { e1.printStackTrace(); } throw new WCMException("Unable to copy resource.", e); } catch (WCMException e) { try { if (session.itemExists(destination)) session.removeItem(destination); } catch (RepositoryException e1) { e1.printStackTrace(); } throw e; } } @Override public void delete(Page page, boolean shallow) throws WCMException { delete(page, shallow, true); } @Override public void delete(Page page, boolean shallow, boolean autoSave) throws WCMException { if (page == null) return; if (!shallow) delete(page.adaptTo(Resource.class), false, autoSave); else delete(page.getContentResource(), true, autoSave); } @Override public void delete(Resource resource, boolean shallow) throws WCMException { delete(resource, shallow, true); } @Override public void delete(Resource resource, boolean shallow, boolean autoSave) throws WCMException { if (resource == null) return; Node node = resource.adaptTo(Node.class); if (node == null) return; try { session.removeItem(node.getPath()); if (autoSave) { session.save(); } } catch (RepositoryException e) { throw new WCMException("Could not delete resource.", e); } } @Override public void order(Page page, String beforeName) throws WCMException { order(page, beforeName, true); } @Override public void order(Page page, String beforeName, boolean autoSave) throws WCMException { if (page == null) return; order(page.getContentResource(), beforeName, autoSave); } @Override public void order(Resource resource, String beforeName) throws WCMException { order(resource, beforeName, true); } @Override public void order(Resource resource, String beforeName, boolean autoSave) throws WCMException { throw new UnsupportedOperationException(); } @Override public Template getTemplate(String s) { throw new UnsupportedOperationException(); } @Override public Collection<Template> getTemplates(String s) { throw new UnsupportedOperationException(); } @Override @SuppressWarnings("deprecation") public Collection<Blueprint> getBlueprints(String s) { throw new UnsupportedOperationException(); } @Override public Revision createRevision(Page page) throws WCMException { throw new UnsupportedOperationException(); } @Override public Revision createRevision(Page page, String s, String s1) throws WCMException { throw new UnsupportedOperationException(); } @Override public Collection<Revision> getRevisions(String s, Calendar calendar) throws WCMException { throw new UnsupportedOperationException(); } @Override public Collection<Revision> getRevisions(String s, Calendar calendar, boolean b) throws WCMException { throw new UnsupportedOperationException(); } @Override public Collection<Revision> getChildRevisions(String s, Calendar calendar) throws WCMException { throw new UnsupportedOperationException(); } @Override public Collection<Revision> getChildRevisions(String s, Calendar calendar, boolean b) throws WCMException { throw new UnsupportedOperationException(); } @Override public Collection<Revision> getChildRevisions(String s, String s1, Calendar calendar) throws WCMException { throw new UnsupportedOperationException(); } @Override public Page restore(String s, String s1) throws WCMException { throw new UnsupportedOperationException(); } @Override public Page restoreTree(String s, Calendar calendar) throws WCMException { throw new UnsupportedOperationException(); } @Override public Page restoreTree(String s, Calendar calendar, boolean b) throws WCMException { throw new UnsupportedOperationException(); } @Override public void touch(Node node, boolean b, Calendar calendar, boolean b1) throws WCMException { throw new UnsupportedOperationException(); } }