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.ParseException; 024import java.text.SimpleDateFormat; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Calendar; 028import java.util.Collections; 029import java.util.Date; 030import java.util.HashMap; 031import java.util.List; 032import java.util.Map; 033 034import javax.jcr.Binary; 035import javax.jcr.Node; 036import javax.jcr.RepositoryException; 037import javax.jcr.Session; 038import javax.jcr.Value; 039import javax.jcr.ValueFactory; 040 041import org.apache.avalon.framework.parameters.Parameters; 042import org.apache.avalon.framework.service.ServiceException; 043import org.apache.avalon.framework.service.ServiceManager; 044import org.apache.cocoon.acting.ServiceableAction; 045import org.apache.cocoon.environment.ObjectModelHelper; 046import org.apache.cocoon.environment.Redirector; 047import org.apache.cocoon.environment.Request; 048import org.apache.cocoon.environment.SourceResolver; 049import org.apache.cocoon.servlet.multipart.PartOnDisk; 050import org.apache.commons.lang3.StringUtils; 051 052import org.ametys.core.cocoon.JSonReader; 053import org.ametys.plugins.repositoryapp.RepositoryProvider; 054import org.ametys.runtime.i18n.I18nizableText; 055import org.ametys.workspaces.repository.jcr.RepositoryDao; 056 057/** 058 * Set value for a property (if the property does not exist, create the property) 059 */ 060public class SetPropertyAction extends ServiceableAction 061{ 062 063 /** The input date format. */ 064 protected static final DateFormat _DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 065 066 /** The repository provider. */ 067 protected RepositoryProvider _repositoryProvider; 068 069 @Override 070 public void service(ServiceManager serviceManager) throws ServiceException 071 { 072 super.service(serviceManager); 073 _repositoryProvider = (RepositoryProvider) serviceManager.lookup(RepositoryProvider.ROLE); 074 } 075 076 public Map act(Redirector redirector, SourceResolver sourceResolver, Map objectModel, String source, Parameters parameters) throws Exception 077 { 078 Map<String, Object> result = new HashMap<>(); 079 080 Request request = ObjectModelHelper.getRequest(objectModel); 081 082 String workspaceName = request.getParameter("workspace"); 083 084 Session session = _repositoryProvider.getSession(workspaceName); 085 086 String nodePath = request.getParameter("path"); 087 String propertyName = request.getParameter("name"); 088 String[] values = request.getParameterValues("value"); 089 String type = request.getParameter("type"); 090 boolean multiple = Boolean.valueOf(request.getParameter("multiple")); 091 092 if (getLogger().isDebugEnabled()) 093 { 094 getLogger().debug("Trying to add property: '" + propertyName + "' to the node at path: '" + nodePath + "'"); 095 } 096 097 String relPath = RepositoryDao.removeLeadingSlash(nodePath); 098 099 // Get the parent node 100 Node node = null; 101 if (StringUtils.isEmpty(relPath)) 102 { 103 node = session.getRootNode(); 104 } 105 else 106 { 107 node = session.getRootNode().getNode(relPath); 108 } 109 110 // Get the type in jcr format (e.g. javax.jcr.PropertyType.BOOLEAN) 111 int jcrType = javax.jcr.PropertyType.valueFromName(StringUtils.capitalize(type)); 112 113 try 114 { 115 // Add or update property to the node 116 if (type.equalsIgnoreCase("Date")) 117 { 118 _setDate(node, propertyName, values); 119 } 120 else if (type.equalsIgnoreCase("Binary")) 121 { 122 _setBinary(session, request, node, propertyName); 123 } 124 else if (type.equalsIgnoreCase("Reference")) 125 { 126 _setReference(session, node, propertyName, values, multiple); 127 } 128 else 129 { 130 _setValue(node, propertyName, values, multiple, jcrType); 131 } 132 133 result.put("success", true); 134 } 135 catch (RepositoryException e) 136 { 137 getLogger().error("Unable to set value " + Arrays.toString(values) + " for property '" + propertyName + "'", e); 138 result.put("success", false); 139 result.put("message", e.toString()); 140 } 141 catch (ParseException e) 142 { 143 getLogger().error("Unable to set value " + Arrays.toString(values) + " for property '" + propertyName + "'", e); 144 result.put("success", false); 145 I18nizableText message = new I18nizableText("plugin.repositoryapp", "PLUGINS_REPOSITORYAPP_CREATE_PROP_ERROR_DATE", Collections.singletonMap("error", new I18nizableText(e.getMessage()))); 146 result.put("message", message); 147 } 148 catch (Exception e) 149 { 150 getLogger().error("Unable to set value " + Arrays.toString(values) + " for property '" + propertyName + "'", e); 151 result.put("success", false); 152 result.put("message", e.toString()); 153 } 154 155 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 156 return EMPTY_MAP; 157 } 158 159 private void _setDate(Node node, String propertyName, String[] value) throws RepositoryException, ParseException 160 { 161 //create calendar date from string value 162 Date date = _DATE_FORMAT.parse(value[0]); 163 Calendar cal = Calendar.getInstance(); 164 cal.setTime(date); 165 166 node.setProperty(propertyName, cal); 167 } 168 169 private void _setBinary(Session session, Request request, Node node, String propertyName) throws RepositoryException, IOException 170 { 171 // The upload was either sent as the property name (when modified) or as "fieldValue" (when added). 172 PartOnDisk uploadedFilePart = (PartOnDisk) request.get(propertyName); 173 if (uploadedFilePart == null) 174 { 175 uploadedFilePart = (PartOnDisk) request.get("fieldValue"); 176 } 177 178 File uploadedFile = (uploadedFilePart != null) ? uploadedFilePart.getFile() : null; 179 InputStream is = new FileInputStream(uploadedFile); 180 181 Binary binary = session.getValueFactory().createBinary(is); 182 node.setProperty(propertyName, binary); 183 } 184 185 private void _setReference(Session session, Node node, String propertyName, String[] value, boolean multiple) throws RepositoryException 186 { 187 List<Value> values = new ArrayList<>(); 188 ValueFactory vf = session.getValueFactory(); 189 for (String v : value) 190 { 191 values.add(vf.createValue(session.getNodeByIdentifier(v))); 192 } 193 194 boolean isMultiple = multiple || node.hasProperty(propertyName) && node.getProperty(propertyName).getDefinition().isMultiple(); 195 if (isMultiple) 196 { 197 node.setProperty(propertyName, values.toArray(new Value[values.size()])); 198 } 199 else 200 { 201 node.setProperty(propertyName, values.get(0)); 202 } 203 } 204 205 private void _setValue(Node node, String propertyName, String[] value, boolean multiple, int jcrType) throws RepositoryException 206 { 207 boolean isMultiple = multiple || node.hasProperty(propertyName) && node.getProperty(propertyName).getDefinition().isMultiple(); 208 if (isMultiple) 209 { 210 node.setProperty(propertyName, value, jcrType); 211 } 212 else 213 { 214 node.setProperty(propertyName, value[0], jcrType); 215 } 216 } 217 218}