/**
* 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.net.URI;
import java.net.URISyntaxException;
import javax.jcr.Credentials;
import javax.jcr.Repository;
import javax.jcr.SimpleCredentials;
import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.util.ObjectHelper;
/**
* The jcr component allows you to add/read nodes to/from a JCR compliant content repository.
*/
@UriEndpoint(firstVersion = "1.3.0", scheme = "jcr", title = "JCR", syntax = "jcr:host/base", alternativeSyntax = "jcr:username:password@host/base",
consumerClass = JcrConsumer.class, label = "cms,database")
public class JcrEndpoint extends DefaultEndpoint {
private Credentials credentials;
private Repository repository;
@UriPath @Metadata(required = "true")
private String host;
@UriPath
private String base;
@UriParam
private String username;
@UriParam
private String password;
@UriParam
private int eventTypes;
@UriParam
private boolean deep;
@UriParam
private String uuids;
@UriParam
private String nodeTypeNames;
@UriParam
private boolean noLocal;
@UriParam(defaultValue = "3000")
private long sessionLiveCheckIntervalOnStart = 3000L;
@UriParam(defaultValue = "60000")
private long sessionLiveCheckInterval = 60000L;
@UriParam
private String workspaceName;
protected JcrEndpoint(String endpointUri, JcrComponent component) {
super(endpointUri, component);
try {
URI uri = new URI(endpointUri);
if (uri.getUserInfo() != null) {
String[] creds = uri.getUserInfo().split(":");
this.username = creds[0];
this.password = creds.length > 1 ? creds[1] : "";
}
this.host = uri.getHost();
this.base = uri.getPath().replaceAll("^/", "");
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI: " + endpointUri, e);
}
}
public Consumer createConsumer(Processor processor) throws Exception {
JcrConsumer answer = new JcrConsumer(this, processor);
configureConsumer(answer);
return answer;
}
public Producer createProducer() throws Exception {
return new JcrProducer(this);
}
public boolean isSingleton() {
return true;
}
@Override
protected void doStart() throws Exception {
super.doStart();
ObjectHelper.notEmpty(host, "host", this);
this.repository = getCamelContext().getRegistry().lookupByNameAndType(host, Repository.class);
if (repository == null) {
throw new RuntimeCamelException("No JCR repository defined under '" + host + "'");
}
if (username != null && password != null) {
this.credentials = new SimpleCredentials(username, password.toCharArray());
}
}
public String getHost() {
return host;
}
/**
* Name of the {@link javax.jcr.Repository} to lookup from the Camel registry to be used.
*/
public void setHost(String host) {
this.host = host;
}
/**
* Get the {@link Repository}
*
* @return the repository
*/
protected Repository getRepository() {
return repository;
}
/**
* Get the {@link Credentials} for establishing the JCR repository connection
*
* @return the credentials
*/
protected Credentials getCredentials() {
return credentials;
}
/**
* Get the base node when accessing the repository
*
* @return the base node
*/
protected String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
public String getUsername() {
return username;
}
/**
* Username for login
*/
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
/**
* Password for login
*/
public void setPassword(String password) {
this.password = password;
}
/**
* <code>eventTypes</code> (a combination of one or more event types encoded
* as a bit mask value such as javax.jcr.observation.Event.NODE_ADDED, javax.jcr.observation.Event.NODE_REMOVED, etc.).
*
* @return eventTypes
* @see {@link javax.jcr.observation.Event}
* @see {@link javax.jcr.observation.ObservationManager#addEventListener(javax.jcr.observation.EventListener, int, String, boolean, String[], String[], boolean)}
*/
public int getEventTypes() {
return eventTypes;
}
public void setEventTypes(int eventTypes) {
this.eventTypes = eventTypes;
}
/**
* When <code>isDeep</code> is true, events whose associated parent node is at
* <code>absPath</code> or within its subgraph are received.
* @return deep
*/
public boolean isDeep() {
return deep;
}
public void setDeep(boolean deep) {
this.deep = deep;
}
/**
* When a comma separated uuid list string is set, only events whose associated parent node has one of
* the identifiers in the comma separated uuid list will be received.
* @return comma separated uuid list string
*/
public String getUuids() {
return uuids;
}
public void setUuids(String uuids) {
this.uuids = uuids;
}
/**
* When a comma separated <code>nodeTypeName</code> list string is set, only events whose associated parent node has
* one of the node types (or a subtype of one of the node types) in this
* list will be received.
*/
public String getNodeTypeNames() {
return nodeTypeNames;
}
public void setNodeTypeNames(String nodeTypeNames) {
this.nodeTypeNames = nodeTypeNames;
}
/**
* If <code>noLocal</code> is <code>true</code>, then events
* generated by the session through which the listener was registered are
* ignored. Otherwise, they are not ignored.
* @return noLocal
*/
public boolean isNoLocal() {
return noLocal;
}
public void setNoLocal(boolean noLocal) {
this.noLocal = noLocal;
}
/**
* Interval in milliseconds to wait before the first session live checking.
* The default value is 3000 ms.
*
* @return sessionLiveCheckIntervalOnStart
*/
public long getSessionLiveCheckIntervalOnStart() {
return sessionLiveCheckIntervalOnStart;
}
public void setSessionLiveCheckIntervalOnStart(long sessionLiveCheckIntervalOnStart) {
if (sessionLiveCheckIntervalOnStart <= 0) {
throw new IllegalArgumentException("sessionLiveCheckIntervalOnStart must be positive value");
}
this.sessionLiveCheckIntervalOnStart = sessionLiveCheckIntervalOnStart;
}
/**
* Interval in milliseconds to wait before each session live checking
* The default value is 60000 ms.
*/
public long getSessionLiveCheckInterval() {
return sessionLiveCheckInterval;
}
public void setSessionLiveCheckInterval(long sessionLiveCheckInterval) {
if (sessionLiveCheckInterval <= 0) {
throw new IllegalArgumentException("sessionLiveCheckInterval must be positive value");
}
this.sessionLiveCheckInterval = sessionLiveCheckInterval;
}
/**
* The workspace to access. If it's not specified then the default one will be used
*/
public String getWorkspaceName() {
return workspaceName;
}
public void setWorkspaceName(String workspaceName) {
this.workspaceName = workspaceName;
}
/**
* Gets the destination name which was configured from the endpoint uri.
*
* @return the destination name resolved from the endpoint uri
*/
public String getEndpointConfiguredDestinationName() {
String remainder = ObjectHelper.after(getEndpointKey(), "//");
if (remainder != null && remainder.contains("@")) {
remainder = remainder.substring(remainder.indexOf('@'));
}
if (remainder != null && remainder.contains("?")) {
// remove parameters
remainder = ObjectHelper.before(remainder, "?");
}
if (ObjectHelper.isEmpty(remainder)) {
return remainder;
}
return remainder;
}
}