001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.component; 018 019import java.io.ByteArrayInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022 023import org.apache.camel.Component; 024import org.apache.camel.api.management.ManagedAttribute; 025import org.apache.camel.api.management.ManagedOperation; 026import org.apache.camel.api.management.ManagedResource; 027import org.apache.camel.api.management.mbean.ManagedResourceEndpointMBean; 028import org.apache.camel.converter.IOConverter; 029import org.apache.camel.impl.ProcessorEndpoint; 030import org.apache.camel.spi.Metadata; 031import org.apache.camel.spi.UriParam; 032import org.apache.camel.spi.UriPath; 033import org.apache.camel.util.IOHelper; 034import org.apache.camel.util.ResourceHelper; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * A useful base class for endpoints which depend on a resource 040 * such as things like Velocity or XQuery based components. 041 */ 042@ManagedResource(description = "Managed ResourceEndpoint") 043public abstract class ResourceEndpoint extends ProcessorEndpoint implements ManagedResourceEndpointMBean { 044 protected final Logger log = LoggerFactory.getLogger(getClass()); 045 private volatile byte[] buffer; 046 047 @UriPath(description = "Path to the resource." 048 + " You can prefix with: classpath, file, http, ref, or bean." 049 + " classpath, file and http loads the resource using these protocols (classpath is default)." 050 + " ref will lookup the resource in the registry." 051 + " bean will call a method on a bean to be used as the resource." 052 + " For bean you can specify the method name after dot, eg bean:myBean.myMethod.") 053 @Metadata(required = "true") 054 private String resourceUri; 055 @UriParam(defaultValue = "false", description = "Sets whether to use resource content cache or not") 056 private boolean contentCache; 057 058 public ResourceEndpoint() { 059 } 060 061 public ResourceEndpoint(String endpointUri, Component component, String resourceUri) { 062 super(endpointUri, component); 063 this.resourceUri = resourceUri; 064 } 065 066 /** 067 * Gets the resource as an input stream considering the cache flag as well. 068 * <p/> 069 * If cache is enabled then the resource content is cached in an internal buffer and this content is 070 * returned to avoid loading the resource over and over again. 071 * 072 * @return the input stream 073 * @throws IOException is thrown if error loading the content of the resource to the local cache buffer 074 */ 075 public InputStream getResourceAsInputStream() throws IOException { 076 // try to get the resource input stream 077 InputStream is; 078 if (isContentCache()) { 079 synchronized (this) { 080 if (buffer == null) { 081 log.debug("Reading resource: {} into the content cache", resourceUri); 082 is = getResourceAsInputStreamWithoutCache(); 083 buffer = IOConverter.toBytes(is); 084 IOHelper.close(is, resourceUri, log); 085 } 086 } 087 log.debug("Using resource: {} from the content cache", resourceUri); 088 return new ByteArrayInputStream(buffer); 089 } 090 091 return getResourceAsInputStreamWithoutCache(); 092 } 093 094 protected InputStream getResourceAsInputStreamWithoutCache() throws IOException { 095 return loadResource(resourceUri); 096 } 097 098 /** 099 * Loads the given resource. 100 * 101 * @param uri uri of the resource. 102 * @return the loaded resource 103 * @throws IOException is thrown if resource is not found or cannot be loaded 104 */ 105 protected InputStream loadResource(String uri) throws IOException { 106 return ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), uri); 107 } 108 109 @ManagedAttribute(description = "Whether the resource is cached") 110 public boolean isContentCache() { 111 return contentCache; 112 } 113 114 @ManagedOperation(description = "Clears the cached resource, forcing to re-load the resource on next request") 115 public void clearContentCache() { 116 log.debug("Clearing resource: {} from the content cache", resourceUri); 117 buffer = null; 118 } 119 120 public boolean isContentCacheCleared() { 121 return buffer == null; 122 } 123 124 @ManagedAttribute(description = "Camel context ID") 125 public String getCamelId() { 126 return getCamelContext().getName(); 127 } 128 129 @ManagedAttribute(description = "Camel ManagementName") 130 public String getCamelManagementName() { 131 return getCamelContext().getManagementName(); 132 } 133 134 @ManagedAttribute(description = "Endpoint service state") 135 public String getState() { 136 return getStatus().name(); 137 } 138 139 /** 140 * Sets whether to use resource content cache or not. 141 */ 142 public void setContentCache(boolean contentCache) { 143 this.contentCache = contentCache; 144 } 145 146 public String getResourceUri() { 147 return resourceUri; 148 } 149 150 /** 151 * Path to the resource. 152 * <p/> 153 * You can prefix with: classpath, file, http, ref, or bean. 154 * classpath, file and http loads the resource using these protocols (classpath is default). 155 * ref will lookup the resource in the registry. 156 * bean will call a method on a bean to be used as the resource. 157 * For bean you can specify the method name after dot, eg bean:myBean.myMethod 158 * 159 * @param resourceUri the resource path 160 */ 161 public void setResourceUri(String resourceUri) { 162 this.resourceUri = resourceUri; 163 } 164}