/** * 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.camel.component.jcr; import java.io.InputStream; import java.math.BigDecimal; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.TypeConverter; import org.apache.camel.impl.DefaultProducer; import org.apache.camel.util.ObjectHelper; import org.apache.jackrabbit.util.Text; public class JcrProducer extends DefaultProducer { public JcrProducer(JcrEndpoint jcrEndpoint) throws RepositoryException { super(jcrEndpoint); } public void process(Exchange exchange) throws Exception { TypeConverter converter = exchange.getContext().getTypeConverter(); Session session = openSession(); Message message = exchange.getIn(); String operation = determineOperation(message); try { if (JcrConstants.JCR_INSERT.equals(operation)) { Node base = findOrCreateNode(session.getRootNode(), getJcrEndpoint().getBase(), ""); Node node = findOrCreateNode(base, getNodeName(message), getNodeType(message)); Map<String, Object> headers = filterComponentHeaders(message.getHeaders()); for (String key : headers.keySet()) { Object header = message.getHeader(key); if (header != null && Object[].class.isAssignableFrom(header.getClass())) { Value[] value = converter.convertTo(Value[].class, exchange, header); node.setProperty(key, value); } else { Value value = converter.convertTo(Value.class, exchange, header); node.setProperty(key, value); } } node.addMixin("mix:referenceable"); exchange.getOut().setBody(node.getIdentifier()); session.save(); } else if (JcrConstants.JCR_GET_BY_ID.equals(operation)) { Node node = session.getNodeByIdentifier(exchange.getIn() .getMandatoryBody(String.class)); PropertyIterator properties = node.getProperties(); while (properties.hasNext()) { Property property = properties.nextProperty(); Class<?> aClass = classForJCRType(property); Object value; if (property.isMultiple()) { value = converter.convertTo(aClass, exchange, property.getValues()); } else { value = converter.convertTo(aClass, exchange, property.getValue()); } message.setHeader(property.getName(), value); } } else { throw new RuntimeException("Unsupported operation: " + operation); } } finally { if (session != null && session.isLive()) { session.logout(); } } } private Map<String, Object> filterComponentHeaders(Map<String, Object> properties) { Map<String, Object> result = new HashMap<String, Object>(properties.size()); for (Map.Entry<String, Object> entry : properties.entrySet()) { String key = entry.getKey(); if (!key.equals(JcrConstants.JCR_NODE_NAME) && !key.equals(JcrConstants.JCR_OPERATION) && !key.equals(JcrConstants.JCR_NODE_TYPE)) { result.put(entry.getKey(), entry.getValue()); } } return result; } private Class<?> classForJCRType(Property property) throws RepositoryException { switch (property.getType()) { case PropertyType.STRING: return String.class; case PropertyType.BINARY: return InputStream.class; case PropertyType.BOOLEAN: return Boolean.class; case PropertyType.LONG: return Long.class; case PropertyType.DOUBLE: return Double.class; case PropertyType.DECIMAL: return BigDecimal.class; case PropertyType.DATE: return Calendar.class; case PropertyType.NAME: return String.class; case PropertyType.PATH: return String.class; case PropertyType.REFERENCE: return String.class; case PropertyType.WEAKREFERENCE: return String.class; case PropertyType.URI: return String.class; case PropertyType.UNDEFINED: return String.class; default: throw new IllegalArgumentException("unknown type: " + property.getType()); } } private String determineOperation(Message message) { String operation = message.getHeader(JcrConstants.JCR_OPERATION, String.class); return operation != null ? operation : JcrConstants.JCR_INSERT; } private String getNodeName(Message message) { String nodeName = message.getHeader(JcrConstants.JCR_NODE_NAME, String.class); return nodeName != null ? nodeName : message.getExchange().getExchangeId(); } private String getNodeType(Message message) { String nodeType = message.getHeader(JcrConstants.JCR_NODE_TYPE, String.class); return nodeType != null ? nodeType : ""; } private Node findOrCreateNode(Node parent, String path, String nodeType) throws RepositoryException { Node result = parent; for (String component : path.split("/")) { component = Text.escapeIllegalJcrChars(component); if (component.length() > 0) { if (result.hasNode(component)) { result = result.getNode(component); } else { if (ObjectHelper.isNotEmpty(nodeType)) { result = result.addNode(component, nodeType); } else { result = result.addNode(component); } } } } return result; } protected Session openSession() throws RepositoryException { if (ObjectHelper.isEmpty(getJcrEndpoint().getWorkspaceName())) { return getJcrEndpoint().getRepository().login(getJcrEndpoint().getCredentials()); } else { return getJcrEndpoint().getRepository().login(getJcrEndpoint().getCredentials(), getJcrEndpoint().getWorkspaceName()); } } private JcrEndpoint getJcrEndpoint() { return (JcrEndpoint)getEndpoint(); } }