001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repositoryapp.jcr; 017 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.text.DateFormat; 023import java.text.SimpleDateFormat; 024import java.time.ZonedDateTime; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Calendar; 028import java.util.GregorianCalendar; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033import javax.jcr.Binary; 034import javax.jcr.Node; 035import javax.jcr.RepositoryException; 036import javax.jcr.Session; 037import javax.jcr.Value; 038import javax.jcr.ValueFactory; 039 040import org.apache.avalon.framework.parameters.Parameters; 041import org.apache.avalon.framework.service.ServiceException; 042import org.apache.avalon.framework.service.ServiceManager; 043import org.apache.cocoon.acting.ServiceableAction; 044import org.apache.cocoon.environment.ObjectModelHelper; 045import org.apache.cocoon.environment.Redirector; 046import org.apache.cocoon.environment.Request; 047import org.apache.cocoon.environment.SourceResolver; 048import org.apache.cocoon.servlet.multipart.PartOnDisk; 049import org.apache.commons.lang3.StringUtils; 050 051import org.ametys.core.cocoon.JSonReader; 052import org.ametys.core.util.DateUtils; 053import org.ametys.plugins.repositoryapp.RepositoryProvider; 054import org.ametys.workspaces.repository.jcr.RepositoryDao; 055 056/** 057 * Set value for a property (if the property does not exist, create the property) 058 */ 059public class SetPropertyAction extends ServiceableAction 060{ 061 062 /** The input date format. */ 063 protected static final DateFormat _DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 064 065 /** The repository provider. */ 066 protected RepositoryProvider _repositoryProvider; 067 068 @Override 069 public void service(ServiceManager serviceManager) throws ServiceException 070 { 071 super.service(serviceManager); 072 _repositoryProvider = (RepositoryProvider) serviceManager.lookup(RepositoryProvider.ROLE); 073 } 074 075 public Map act(Redirector redirector, SourceResolver sourceResolver, Map objectModel, String source, Parameters parameters) throws Exception 076 { 077 Map<String, Object> result = new HashMap<>(); 078 079 Request request = ObjectModelHelper.getRequest(objectModel); 080 081 String workspaceName = request.getParameter("workspace"); 082 083 Session session = _repositoryProvider.getSession(workspaceName); 084 085 String nodePath = request.getParameter("path"); 086 String propertyName = request.getParameter("name"); 087 String[] values = request.getParameterValues("value"); 088 String type = request.getParameter("type"); 089 boolean multiple = Boolean.valueOf(request.getParameter("multiple")); 090 091 if (getLogger().isDebugEnabled()) 092 { 093 getLogger().debug("Trying to add property: '" + propertyName + "' to the node at path: '" + nodePath + "'"); 094 } 095 096 String relPath = RepositoryDao.removeLeadingSlash(nodePath); 097 098 // Get the parent node 099 Node node = null; 100 if (StringUtils.isEmpty(relPath)) 101 { 102 node = session.getRootNode(); 103 } 104 else 105 { 106 node = session.getRootNode().getNode(relPath); 107 } 108 109 // Get the type in jcr format (e.g. javax.jcr.PropertyType.BOOLEAN) 110 int jcrType = javax.jcr.PropertyType.valueFromName(StringUtils.capitalize(type)); 111 112 try 113 { 114 // Add or update property to the node 115 if (type.equalsIgnoreCase("Date")) 116 { 117 _setDate(node, propertyName, values); 118 } 119 else if (type.equalsIgnoreCase("Binary")) 120 { 121 _setBinary(session, request, node, propertyName); 122 } 123 else if (type.equalsIgnoreCase("Reference")) 124 { 125 _setReference(session, node, propertyName, values, multiple); 126 } 127 else 128 { 129 _setValue(node, propertyName, values, multiple, jcrType); 130 } 131 132 result.put("success", true); 133 } 134 catch (Exception e) 135 { 136 getLogger().error("Unable to set value " + Arrays.toString(values) + " for property '" + propertyName + "'", e); 137 result.put("success", false); 138 result.put("message", e.toString()); 139 } 140 141 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 142 return EMPTY_MAP; 143 } 144 145 private void _setDate(Node node, String propertyName, String[] value) throws RepositoryException 146 { 147 //create calendar date from string value 148 ZonedDateTime zdt = DateUtils.parseZonedDateTime(value[0]); 149 Calendar cal = GregorianCalendar.from(zdt); 150 151 node.setProperty(propertyName, cal); 152 } 153 154 private void _setBinary(Session session, Request request, Node node, String propertyName) throws RepositoryException, IOException 155 { 156 // The upload was either sent as the property name (when modified) or as "fieldValue" (when added). 157 PartOnDisk uploadedFilePart = (PartOnDisk) request.get(propertyName); 158 if (uploadedFilePart == null) 159 { 160 uploadedFilePart = (PartOnDisk) request.get("fieldValue"); 161 } 162 163 File uploadedFile = (uploadedFilePart != null) ? uploadedFilePart.getFile() : null; 164 InputStream is = new FileInputStream(uploadedFile); 165 166 Binary binary = session.getValueFactory().createBinary(is); 167 node.setProperty(propertyName, binary); 168 } 169 170 private void _setReference(Session session, Node node, String propertyName, String[] value, boolean multiple) throws RepositoryException 171 { 172 List<Value> values = new ArrayList<>(); 173 ValueFactory vf = session.getValueFactory(); 174 for (String v : value) 175 { 176 values.add(vf.createValue(session.getNodeByIdentifier(v))); 177 } 178 179 boolean isMultiple = multiple || node.hasProperty(propertyName) && node.getProperty(propertyName).getDefinition().isMultiple(); 180 if (isMultiple) 181 { 182 node.setProperty(propertyName, values.toArray(new Value[values.size()])); 183 } 184 else 185 { 186 node.setProperty(propertyName, values.get(0)); 187 } 188 } 189 190 private void _setValue(Node node, String propertyName, String[] value, boolean multiple, int jcrType) throws RepositoryException 191 { 192 boolean isMultiple = multiple || node.hasProperty(propertyName) && node.getProperty(propertyName).getDefinition().isMultiple(); 193 if (isMultiple) 194 { 195 node.setProperty(propertyName, value, jcrType); 196 } 197 else 198 { 199 node.setProperty(propertyName, value[0], jcrType); 200 } 201 } 202 203}