001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.camel;
019
020import static org.apache.commons.lang3.StringUtils.isBlank;
021
022import java.net.URI;
023
024import org.apache.camel.Consumer;
025import org.apache.camel.Processor;
026import org.apache.camel.Producer;
027import org.apache.camel.RuntimeCamelException;
028import org.apache.camel.api.management.ManagedAttribute;
029import org.apache.camel.api.management.ManagedResource;
030import org.apache.camel.impl.DefaultEndpoint;
031import org.apache.camel.spi.UriEndpoint;
032import org.springframework.transaction.PlatformTransactionManager;
033import org.springframework.transaction.TransactionDefinition;
034import org.springframework.transaction.support.TransactionTemplate;
035
036/**
037 * Represents a Fcrepo endpoint.
038 * @author Aaron Coburn
039 * @since October 20, 2014
040 */
041@ManagedResource(description = "Managed FcrepoEndpoint")
042@UriEndpoint(scheme = "fcrepo", title = "Fedora Commons Repository", syntax = "fcrepo:host:port/path")
043public class FcrepoEndpoint extends DefaultEndpoint {
044
045    private FcrepoConfiguration configuration;
046
047    private PlatformTransactionManager transactionManager;
048
049    public static final int DEFAULT_HTTPS_PORT = 443;
050
051    /**
052     * Create a FcrepoEndpoint with a uri, path and component
053     * @param uri the endpoint uri (without path values)
054     * @param remaining any path values on the endpoint uri
055     * @param component an existing component value
056     * @param configuration configuration settings for this endpoint
057     */
058    public FcrepoEndpoint(final String uri, final String remaining, final FcrepoComponent component,
059            final FcrepoConfiguration configuration) {
060        super(uri, component);
061        this.configuration = configuration;
062        this.transactionManager = component.getTransactionManager();
063        if (isBlank(configuration.getBaseUrl())) {
064            setBaseUrl(remaining);
065        }
066    }
067
068    /**
069     * Create a producer endpoint.
070     *
071     * @return A new camel producer endpoint
072     */
073    @Override
074    public Producer createProducer() {
075        return new FcrepoProducer(this);
076    }
077
078    /**
079     * This component does not implement a consumer endpoint.
080     */
081    @Override
082    public Consumer createConsumer(final Processor processor) {
083        throw new RuntimeCamelException("Cannot consume from a FcrepoEndpoint: " + getEndpointUri());
084    }
085
086    /**
087     * Define the component as a singleton
088     *
089     * @return whether the endpoint is implemented as a singleton.
090     */
091    @Override
092    public boolean isSingleton() {
093        return true;
094    }
095
096    /**
097     * Create a template for use in transactions
098     *
099     * @return a transaction template
100     */
101    public TransactionTemplate createTransactionTemplate() {
102        TransactionTemplate transactionTemplate;
103
104        if (getTransactionManager() != null) {
105            transactionTemplate = new TransactionTemplate(getTransactionManager());
106        } else {
107            final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
108            txMgr.setBaseUrl(getBaseUrlWithScheme());
109            txMgr.setAuthUsername(getAuthUsername());
110            txMgr.setAuthPassword(getAuthPassword());
111            txMgr.setAuthHost(getAuthHost());
112            transactionTemplate = new TransactionTemplate(txMgr);
113        }
114        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
115        transactionTemplate.afterPropertiesSet();
116        return transactionTemplate;
117    }
118
119    /**
120     * Get the repository baseUrl with a full scheme.
121     * The base URL may be any of the following:
122     * localhost:8080/rest
123     * fedora.institution.org:8983/rest
124     * http://localhost:8080/fcrepo/rest
125     * https://fedora.institution.org/rest
126     * fedora.insitution.org:443/rest
127     *
128     * This method ensures that the url (fragment) is properly prefixed
129     * with either the http or https scheme, suitable for sending to the
130     * httpclient.
131     *
132     * @return String
133     */
134    public String getBaseUrlWithScheme() {
135        final StringBuilder url = new StringBuilder();
136        final String baseUrl = getBaseUrl();
137
138        if (!baseUrl.startsWith("http:") && !baseUrl.startsWith("https:")) {
139            if (URI.create("http://" + baseUrl).getPort() == DEFAULT_HTTPS_PORT) {
140                url.append("https://");
141            } else {
142                url.append("http://");
143            }
144        }
145        url.append(baseUrl);
146        return url.toString();
147    }
148
149    /**
150     * configuration getter
151     *
152     * @return the component configuration
153     */
154    public FcrepoConfiguration getConfiguration() {
155        return configuration;
156    }
157
158    /**
159     * configuration setter
160     * 
161     * @param config The FcrepoConfiguration
162     */
163    public void setConfiguration(final FcrepoConfiguration config) {
164        this.configuration = config;
165    }
166
167    /**
168     * baseUrl setter
169     *
170     * @param url the fcrepo base url
171     */
172    public void setBaseUrl(final String url) {
173        getConfiguration().setBaseUrl(url);
174    }
175
176    /**
177     * baseUrl getter
178     *
179     * @return the fcrepo base url
180     */
181    public String getBaseUrl() {
182        return getConfiguration().getBaseUrl();
183    }
184
185    /**
186     * transactionManager setter
187     *
188     * @param transactionManager the transaction manager for this endpoint
189     */
190    @ManagedAttribute(description = "Transaction Manager")
191    public void setTransactionManager(final PlatformTransactionManager transactionManager) {
192        this.transactionManager = transactionManager;
193    }
194
195    /**
196     * transactionManager getter
197     *
198     * @return the transaction manager for this endpoint
199     */
200    @ManagedAttribute(description = "Transaction Manager")
201    public PlatformTransactionManager getTransactionManager() {
202        return transactionManager;
203    }
204
205    /**
206     * accept setter
207     *
208     * @param type the mime-type used with Accept headers
209     */
210    @ManagedAttribute(description = "Accept: Header")
211    public void setAccept(final String type) {
212        getConfiguration().setAccept(type.replaceAll(" ", "+"));
213    }
214
215    /**
216     * accept getter
217     *
218     * @return the mime-type used with Accept headers
219     */
220    @ManagedAttribute(description = "Accept: Header")
221    public String getAccept() {
222        return getConfiguration().getAccept();
223    }
224
225    /**
226     * contentType setter
227     * 
228     * @param type the mime-type used with Content-Type headers
229     */
230    @ManagedAttribute(description = "Content-Type: Header")
231    public void setContentType(final String type) {
232        getConfiguration().setContentType(type);
233    }
234
235    /**
236     * contentType getter
237     *
238     * @return the mime-type used with Content-Type headers
239     */
240    @ManagedAttribute(description = "Content-Type: Header")
241    public String getContentType() {
242        return getConfiguration().getContentType();
243    }
244
245    /**
246     * authUsername setter
247     * 
248     * @param username used for repository authentication
249     */
250    @ManagedAttribute(description = "Username for authentication")
251    public void setAuthUsername(final String username) {
252        getConfiguration().setAuthUsername(username);
253    }
254
255    /**
256     * authUsername getter
257     *
258     * @return the username used for repository authentication
259     */
260    @ManagedAttribute(description = "Username for authentication")
261    public String getAuthUsername() {
262        return getConfiguration().getAuthUsername();
263    }
264
265    /**
266     * authPassword setter
267     * 
268     * @param password used for repository authentication
269     */
270    @ManagedAttribute(description = "Password for authentication")
271    public void setAuthPassword(final String password) {
272        getConfiguration().setAuthPassword(password);
273    }
274
275    /**
276     * authPassword getter
277     *
278     * @return the password used for repository authentication
279     */
280    @ManagedAttribute(description = "Password for authentication")
281    public String getAuthPassword() {
282        return getConfiguration().getAuthPassword();
283    }
284
285    /**
286     * authHost setter
287     * 
288     * @param host realm used for repository authentication
289     */
290    @ManagedAttribute(description = "Hostname for authentication")
291    public void setAuthHost(final String host) {
292        getConfiguration().setAuthHost(host);
293    }
294
295    /**
296     * authHost getter
297     *
298     * @return the host realm used for repository authentication
299     */
300    @ManagedAttribute(description = "Hostname for authentication")
301    public String getAuthHost() {
302        return getConfiguration().getAuthHost();
303    }
304
305    /**
306     * metadata setter
307     *
308     * @param metadata whether to retrieve rdf metadata for non-rdf nodes
309     */
310    @ManagedAttribute(description = "Whether to retrieve the /fcr:metadata endpoint for Binary nodes")
311    public void setMetadata(final Boolean metadata) {
312        getConfiguration().setMetadata(metadata);
313    }
314
315    /**
316     * metadata getter
317     *
318     * @return whether to retrieve rdf metadata for non-rdf nodes
319     */
320    @ManagedAttribute(description = "Whether to retrieve the /fcr:metadata endpoint for Binary nodes")
321    public Boolean getMetadata() {
322        return getConfiguration().getMetadata();
323    }
324
325    /**
326     * throwExceptionOnFailure setter
327     *
328     * @param throwOnFailure whether HTTP error codes throw exceptions
329     */
330    @ManagedAttribute(description = "Whether HTTP response errors should throw an exception")
331    public void setThrowExceptionOnFailure(final Boolean throwOnFailure) {
332        getConfiguration().setThrowExceptionOnFailure(throwOnFailure);
333    }
334
335    /**
336     * throwExceptionOnFailure getter
337     *
338     * @return whether HTTP error codes throw exceptions
339     */
340    @ManagedAttribute(description = "Whether HTTP response errors should throw an exception")
341    public Boolean getThrowExceptionOnFailure() {
342        return getConfiguration().getThrowExceptionOnFailure();
343    }
344
345    /**
346     * transform setter
347     * 
348     * @param transform define an LD-Path transform program for converting RDF to JSON
349     */
350    @ManagedAttribute(description = "The LDPath transform program to use")
351    public void setTransform(final String transform) {
352        getConfiguration().setTransform(transform);
353    }
354
355    /**
356     * transform getter
357     *
358     * @return the LD-Path transform program used to convert RDF to JSON
359     */
360    @ManagedAttribute(description = "The LDPath transform program to use")
361    public String getTransform() {
362        return getConfiguration().getTransform();
363    }
364
365    /**
366     * fixity setter
367     *
368     * @param fixity whether to access the /fcr:fixity endpoint for a resource
369     */
370    @ManagedAttribute(description = "Whether to access the /fcr:fixity endpoint for a resource")
371    public void setFixity(final Boolean fixity) {
372        getConfiguration().setFixity(fixity);
373    }
374
375    /**
376     * fixity getter
377     *
378     * @return whether to access the /fcr:fixity endpoint for a resource
379     */
380    @ManagedAttribute(description = "Whether to access the /fcr:fixity endpoint for a resource")
381    public Boolean getFixity() {
382        return getConfiguration().getFixity();
383    }
384
385
386    /**
387     * tombstone setter
388     * 
389     * @param tombstone whether to access the /fcr:tombstone endpoint for a resource
390     */
391    @ManagedAttribute(description = "Whether to use the /fcr:tombstone endpoint on objects")
392    public void setTombstone(final Boolean tombstone) {
393        getConfiguration().setTombstone(tombstone);
394    }
395
396    /**
397     * tombstone getter
398     *
399     * @return whether to access the /fcr:tombstone endpoint for a resource
400     */
401    @ManagedAttribute(description = "Whether to use the /fcr:tombstone endpoint on objects")
402    public Boolean getTombstone() {
403        return getConfiguration().getTombstone();
404    }
405
406    /**
407     * preferInclude setter
408     *
409     * @param include the URI(s) that populate the include section in a Prefer header
410     */
411    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; include=\"URI\" header")
412    public void setPreferInclude(final String include) {
413        getConfiguration().setPreferInclude(include);
414    }
415
416    /**
417     * preferInclude getter
418     *
419     * @return the URI(s) that populate the include section in a Prefer header
420     */
421    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; include=\"URI\" header")
422    public String getPreferInclude() {
423        return getConfiguration().getPreferInclude();
424    }
425
426    /**
427     * preferOmit setter
428     *
429     * @param omit the URI(s) that populate the omit section in a Prefer header
430     */
431    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; omit=\"URI\" header")
432    public void setPreferOmit(final String omit) {
433        getConfiguration().setPreferOmit(omit);
434    }
435
436    /**
437     * preferOmit getter
438     *
439     * @return the URI(s) that populate the omit section in a Prefer header
440     */
441    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; omit=\"URI\" header")
442    public String getPreferOmit() {
443        return getConfiguration().getPreferOmit();
444    }
445}