| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.sling.jcr.resource.internal.helper.jcr; |
| |
| import java.io.InputStream; |
| import java.math.BigDecimal; |
| import java.util.Calendar; |
| import java.util.Iterator; |
| |
| import javax.jcr.Item; |
| import javax.jcr.Node; |
| import javax.jcr.Property; |
| import javax.jcr.PropertyType; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.Value; |
| import javax.jcr.ValueFormatException; |
| |
| import org.apache.sling.adapter.annotations.Adaptable; |
| import org.apache.sling.adapter.annotations.Adapter; |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.api.resource.ResourceMetadata; |
| import org.apache.sling.api.resource.ResourceResolver; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| @Adaptable(adaptableClass = Resource.class, adapters = { |
| @Adapter(value = { Item.class, Property.class, Value.class, String.class, Boolean.class, Long.class, |
| Double.class, BigDecimal.class, Calendar.class, InputStream.class, Value[].class, String[].class, |
| Boolean[].class, Long[].class, Double[].class, BigDecimal[].class }), |
| @Adapter(value = Node.class, condition = "If the resource is a JcrPropertyResource and the property is a reference or weak reference property.") }) |
| class JcrPropertyResource extends JcrItemResource<Property> { // this should be package private, see SLING-1414 |
| |
| /** default log */ |
| private static final Logger LOGGER = LoggerFactory.getLogger(JcrPropertyResource.class); |
| |
| private final String resourceType; |
| |
| public JcrPropertyResource(final ResourceResolver resourceResolver, |
| final String path, |
| final String version, |
| final Property property) throws RepositoryException { |
| super(resourceResolver, path, version, property, new ResourceMetadata()); |
| this.resourceType = getResourceTypeForNode(property.getParent()) |
| + "/" + property.getName(); |
| if (PropertyType.BINARY != getProperty().getType()) { |
| this.getResourceMetadata().setContentType("text/plain"); |
| this.getResourceMetadata().setCharacterEncoding("UTF-8"); |
| } |
| |
| this.getResourceMetadata().setContentLength(getContentLength(property)); |
| } |
| |
| public @NotNull String getResourceType() { |
| return resourceType; |
| } |
| |
| public @Nullable String getResourceSuperType() { |
| return null; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { |
| |
| // the property itself |
| if (type == Property.class || type == Item.class) { |
| return (AdapterType) getProperty(); |
| } |
| |
| // the property value |
| try { |
| if (type == String.class) { |
| return (AdapterType) getProperty().getString(); |
| |
| } else if (type == Boolean.class) { |
| return (AdapterType) Boolean.valueOf(getProperty().getBoolean()); |
| |
| } else if (type == Long.class) { |
| return (AdapterType) Long.valueOf(getProperty().getLong()); |
| |
| } else if (type == Double.class) { |
| return (AdapterType) new Double(getProperty().getDouble()); |
| |
| } else if (type == BigDecimal.class) { |
| return (AdapterType) getProperty().getDecimal(); |
| |
| } else if (type == Calendar.class) { |
| return (AdapterType) getProperty().getDate(); |
| |
| } else if (type == Value.class) { |
| return (AdapterType) getProperty().getValue(); |
| |
| } else if (type == Node.class |
| && (getProperty().getType() == PropertyType.REFERENCE || |
| getProperty().getType() == PropertyType.WEAKREFERENCE)) { |
| return (AdapterType) getProperty().getNode(); |
| |
| } else if (type == InputStream.class) { |
| return (AdapterType) getInputStream(); |
| |
| } else if (type == String[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final String[] result = new String[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getString(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new String[]{getProperty().getString()}; |
| |
| } else if (type == Boolean[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final Boolean[] result = new Boolean[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getBoolean(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new Boolean[]{getProperty().getBoolean()}; |
| |
| } else if (type == Long[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final Long[] result = new Long[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getLong(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new Long[]{getProperty().getLong()}; |
| |
| } else if (type == Double[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final Double[] result = new Double[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getDouble(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new Double[]{getProperty().getDouble()}; |
| |
| } else if (type == BigDecimal[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final BigDecimal[] result = new BigDecimal[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getDecimal(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new BigDecimal[]{getProperty().getDecimal()}; |
| |
| } else if (type == Calendar[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| final Value[] values = getProperty().getValues(); |
| final Calendar[] result = new Calendar[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| result[i] = values[i].getDate(); |
| } |
| return (AdapterType) result; |
| } |
| return (AdapterType) new Calendar[]{getProperty().getDate()}; |
| |
| } else if (type == Value[].class) { |
| if (getProperty().getDefinition().isMultiple()) { |
| return (AdapterType) getProperty().getValues(); |
| } |
| return (AdapterType) new Value[]{getProperty().getValue()}; |
| |
| } |
| |
| } catch (ValueFormatException vfe) { |
| LOGGER.debug("adaptTo: Problem accessing the property value of {}: {}", getPath(), vfe.getMessage()); |
| LOGGER.debug("adaptTo: Cause", vfe); |
| |
| } catch (RepositoryException re) { |
| LOGGER.debug("adaptTo: Problem accessing the property " + getPath(), re); |
| } |
| |
| // try to use adapter factories |
| return super.adaptTo(type); |
| } |
| |
| @Override |
| public String toString() { |
| return getClass().getSimpleName() + ", type=" + getResourceType() + ", path=" + getPath(); |
| } |
| |
| private Property getProperty() { |
| return getItem(); |
| } |
| |
| private InputStream getInputStream() { |
| Property prop = getProperty(); |
| |
| try { |
| return prop.getBinary().getStream(); |
| } catch (RepositoryException re) { |
| LOGGER.error("getInputStream: Problem accessing the property " + getPath() + " stream", re); |
| } |
| |
| // fall back to none in case of an error |
| return null; |
| } |
| |
| @Override |
| Iterator<Resource> listJcrChildren() { |
| return null; |
| } |
| |
| @Override |
| public boolean hasChildren() { |
| return false; |
| } |
| } |