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        final 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 String baseUrl = getBaseUrl();
136
137        if (!baseUrl.startsWith("http:") && !baseUrl.startsWith("https:")) {
138            if (URI.create("http://" + baseUrl).getPort() == DEFAULT_HTTPS_PORT) {
139                return "https://" + baseUrl;
140            } else {
141                return "http://" + baseUrl;
142            }
143        }
144        return baseUrl;
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     * fixity setter
345     *
346     * @param fixity whether to access the /fcr:fixity endpoint for a resource
347     */
348    @ManagedAttribute(description = "Whether to access the /fcr:fixity endpoint for a resource")
349    public void setFixity(final Boolean fixity) {
350        getConfiguration().setFixity(fixity);
351    }
352
353    /**
354     * fixity getter
355     *
356     * @return whether to access the /fcr:fixity endpoint for a resource
357     */
358    @ManagedAttribute(description = "Whether to access the /fcr:fixity endpoint for a resource")
359    public Boolean getFixity() {
360        return getConfiguration().getFixity();
361    }
362
363    /**
364     * preferInclude setter
365     *
366     * @param include the URI(s) that populate the include section in a Prefer header
367     */
368    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; include=\"URI\" header")
369    public void setPreferInclude(final String include) {
370        getConfiguration().setPreferInclude(include);
371    }
372
373    /**
374     * preferInclude getter
375     *
376     * @return the URI(s) that populate the include section in a Prefer header
377     */
378    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; include=\"URI\" header")
379    public String getPreferInclude() {
380        return getConfiguration().getPreferInclude();
381    }
382
383    /**
384     * preferOmit setter
385     *
386     * @param omit the URI(s) that populate the omit section in a Prefer header
387     */
388    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; omit=\"URI\" header")
389    public void setPreferOmit(final String omit) {
390        getConfiguration().setPreferOmit(omit);
391    }
392
393    /**
394     * preferOmit getter
395     *
396     * @return the URI(s) that populate the omit section in a Prefer header
397     */
398    @ManagedAttribute(description = "Whether to include a Prefer: return=representation; omit=\"URI\" header")
399    public String getPreferOmit() {
400        return getConfiguration().getPreferOmit();
401    }
402}