View Javadoc

1   /**
2    * This file Copyright (c) 2013 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.groovy.support.nodes;
35  
36  import java.math.BigDecimal;
37  import java.util.Collection;
38  import java.util.Iterator;
39  
40  import javax.jcr.Node;
41  import javax.jcr.NodeIterator;
42  import javax.jcr.PathNotFoundException;
43  import javax.jcr.Property;
44  import javax.jcr.PropertyIterator;
45  import javax.jcr.PropertyType;
46  import javax.jcr.RepositoryException;
47  import javax.jcr.Value;
48  import javax.jcr.ValueFormatException;
49  
50  import org.apache.commons.lang.StringUtils;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  import groovy.lang.DelegatingMetaClass;
55  import groovy.lang.GroovySystem;
56  import groovy.lang.MetaClass;
57  import info.magnolia.cms.core.MetaData;
58  import info.magnolia.cms.core.MgnlNodeType;
59  import info.magnolia.cms.security.AccessDeniedException;
60  import info.magnolia.jcr.RuntimeRepositoryException;
61  import info.magnolia.jcr.util.NodeUtil;
62  import info.magnolia.jcr.wrapper.ChildWrappingNodeWrapper;
63  
64  /**
65   * Implementation of wrapped Node object used in Groovy console context.
66   */
67  public class MgnlGroovyJCRNode extends ChildWrappingNodeWrapper{
68  
69      protected static final Logger log = LoggerFactory.getLogger(MgnlGroovyJCRNode.class);
70  
71      private String name;
72  
73      public MgnlGroovyJCRNode(Node node) throws RepositoryException {
74          super(node);
75          this.name = node.getName();
76      }
77  
78      protected static void setMetaClass(final MetaClass metaClass, Class nodeClass) {
79          final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
80  
81              @Override
82              public Object getAttribute(final Object object, final String attribute) {
83                  MgnlGroovyJCRNode n = (MgnlGroovyJCRNode) object;
84                  try {
85                      return n.get("@" + attribute);
86                  } catch (RepositoryException e) {
87                      log.error(e.getMessage());
88                      return null;
89                  }
90              }
91  
92              @Override
93              public void setAttribute(final Object object, final String attribute, final Object newValue) {
94                  MgnlGroovyJCRNode n = (MgnlGroovyJCRNode) object;
95                  try {
96                      n.setProperty(attribute, (Value) newValue);
97                  }
98                  catch (AccessDeniedException e) {
99                      log.error(e.getMessage());
100                 }
101                 catch (PathNotFoundException e) {
102                     log.error(e.getMessage());
103                 }
104                 catch (RepositoryException e) {
105                     log.error(e.getMessage());
106                 }
107             }
108 
109             @Override
110             public Object getProperty(Object object, String property) {
111                 if (object instanceof MgnlGroovyJCRNode) {
112                     MgnlGroovyJCRNode n = (MgnlGroovyJCRNode) object;
113                     try {
114                         return n.get(property);
115                     } catch (RepositoryException e) {
116                         log.error(e.getMessage());
117                         return null;
118                     }
119                 }
120                 return super.getProperty(object, property);
121             }
122 
123             @Override
124             public void setProperty(Object object, String property, Object newValue) {
125                 String attribute = null;
126                 if (property.startsWith("@")) {
127                     attribute = property.substring(1);
128                 } else {
129                     attribute = property;
130                 }
131                 MgnlGroovyJCRNode n = (MgnlGroovyJCRNode) object;
132                 try {
133                     if (newValue instanceof Integer) {
134                         newValue = ((Integer) newValue).longValue();
135                     }
136                     n.setProperty(attribute, (Value) newValue);
137                 }
138                 catch (AccessDeniedException e) {
139                     log.error(e.getMessage());
140                 }
141                 catch (PathNotFoundException e) {
142                     log.error(e.getMessage());
143                 }
144                 catch (RepositoryException e) {
145                     log.error(e.getMessage());
146                 }
147             }
148         };
149         GroovySystem.getMetaClassRegistry().setMetaClass(nodeClass, newMetaClass);
150     }
151 
152     public String name() {
153         return name;
154     }
155 
156     public Object get(String key) throws RepositoryException {
157         if (key != null && key.charAt(0) == '@') {
158             String attributeName = key.substring(1);
159             return getPropertyValue(attributeName);
160         }
161         if ("parent".equals(key)) {
162             try {
163                 return getParent();
164             } catch (RepositoryException e) {
165                 log.error(e.getMessage());
166                 return null;
167             }
168         }
169         if ("children".equals(key)) {
170             Collection<Node> retVal = NodeUtil.getCollectionFromNodeIterator(wrapped.getNodes());
171             if (!isContentNodeType()) {
172                 retVal.addAll(NodeUtil.getCollectionFromNodeIterator(NodeUtil.filterNodeType(wrapped.getNodes(), MgnlNodeType.NT_CONTENTNODE)));
173             }
174             return retVal;
175         }
176         if ("metaData".equals(key)) {
177             return new MetaData(wrapped);
178         }
179         if ("nodeData".equals(key)) {
180             return wrapped.getProperties();
181         }
182         if ("name".equals(key)) {
183             return name;
184         }
185         Node retVal = getByName(key);
186         if (retVal != null) {
187             return retVal;
188         }
189         return getPropertyValue(key);
190     }
191 
192     protected Object getPropertyValue(String attributeName) throws RepositoryException {
193         PropertyIterator properties = wrapped.getProperties(attributeName);
194         if (!properties.hasNext()) {
195             return null;
196         }
197         Property nodeData = properties.nextProperty();
198         Value propertyValue = nodeData.getValue();
199         Object value = null;
200         if (propertyValue != null) {
201             try {
202                 switch (propertyValue.getType()) {
203                 case PropertyType.STRING:
204                     value = propertyValue.getString();
205                     break;
206                 case PropertyType.BINARY:
207                     value = propertyValue;
208                     break;
209                 case PropertyType.DATE:
210                     value = propertyValue.getDate();
211                     break;
212                 case PropertyType.DOUBLE:
213                     value = BigDecimal.valueOf(propertyValue.getDouble());
214                     break;
215                 case PropertyType.LONG:
216                     value = BigDecimal.valueOf(propertyValue.getLong());
217                     break;
218                 default:
219                     value = propertyValue.getString();
220                 }
221             } catch (ValueFormatException e) {
222                 log.warn(e.getMessage());
223             } catch (IllegalStateException e) {
224                 log.warn(e.getMessage());
225             } catch (RepositoryException e) {
226                 log.warn(e.getMessage());
227             }
228         }
229         return value;
230     }
231 
232     protected Node getByName(String name) {
233         try{
234             for (Iterator<Node> iter = wrapped.getNodes(); iter.hasNext();) {
235                 Node childNode = iter.next();
236                 String childNodeName = childNode.getName();
237                 if (name.equals(childNodeName)) {
238                     return childNode;
239                 }
240             }
241         }catch(RepositoryException e){
242             log.error(e.getMessage());
243         }
244         return null;
245     }
246 
247     @Override
248     public String toString() {
249         try{
250             StringBuilder retVal = new StringBuilder();
251             Iterator<Node> iterator = wrapped.getNodes();
252             retVal.append("(+) " + name + "\n");
253             while (iterator.hasNext()) {
254                 Node node = iterator.next();
255                 if(showNode(node)){
256                     if (hasMoreChildren(node)) {
257                         retVal.append("\t(+) ");
258                     } else {
259                         retVal.append("\t(-) ");
260                     }
261                     retVal.append(node.getName() + "\n");
262                 }
263             }
264 
265             PropertyIterator properties = wrapped.getProperties();
266             while (properties.hasNext()) {
267                 Property property = properties.nextProperty();
268                 if(showProperty(property)){
269                     retVal.append("\t\t* " + property.getName() + ": ["
270                                 + StringUtils.abbreviate(property.getString(), 80)
271                                 + "]\n");
272                 }
273             }
274     
275             return retVal.toString();
276         }catch(RepositoryException e){
277             log.error(e.toString());
278             return null;
279         }
280     }
281 
282     protected boolean showNode(Node node) {
283         try{
284             if(node.getPrimaryNodeType().getName().equals("mgnl:metaData")){
285                 return false;
286             }else if(StringUtils.startsWith(node.getName(), "jcr:")){
287                 return false;
288             }else if(StringUtils.startsWith(node.getName(), "rep:")){
289                 return false;
290             }
291         }catch(RepositoryException e){
292             log.error(e.getMessage());
293             return false;
294         }
295         return true;
296     }
297     
298     protected boolean showProperty(Property property) {
299         try{
300             if(property.isMultiple()){
301                 return false;
302             }else if(StringUtils.startsWith(property.getName(), "jcr:")){
303                 return false;
304             }
305         }catch(RepositoryException e){
306             log.error(e.getMessage());
307             return false;
308         }
309         return true;
310     }
311 
312     private boolean hasMoreChildren(Node node) throws RepositoryException {
313         boolean hasChildren = false;
314         try{
315             NodeIterator it = node.getNodes();
316             while (it.hasNext()){
317                 if(!it.nextNode().getPrimaryNodeType().getName().equals("mgnl:metaData")){
318                     hasChildren = true;
319                     break;
320                 }
321             }
322         }catch(RepositoryException e){
323             log.error(e.getMessage());
324         }
325         return hasChildren;
326     }
327 
328     @Override
329     public int hashCode() {
330         final int prime = 31;
331         int result = 1;
332         result = prime * result + ((name == null) ? 0 : name.hashCode());
333         return result;
334     }
335 
336     @Override
337     public boolean equals(Object obj) {
338         try{
339             if (this == obj)
340                 return true;
341             if (obj == null)
342                 return false;
343             if (getClass() != obj.getClass())
344                 return false;
345             MgnlGroovyJCRNode other = (MgnlGroovyJCRNode) obj;
346             if (name == null) {
347                 if (other.name != null)
348                     return false;
349             } else if (!wrapped.getPath().equals(other.getPath()))
350                 return false;
351             return true;
352         }catch(RepositoryException e){
353             return false;
354         }
355     }
356 
357     private boolean isContentNodeType() {
358         try {
359             return wrapped.isNodeType(MgnlNodeType.NT_CONTENTNODE);
360         } catch (RepositoryException e) {
361             throw new RuntimeRepositoryException(e);
362         }
363     }
364 }