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