/**
* 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();
}
}