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