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 @UriParam(defaultValue = "false", description = "Sets whether the context map should allow access to all details." 058 + " By default only the message body and headers can be accessed." 059 + " This option can be enabled for full access to the current Exchange and CamelContext." 060 + " Doing so impose a potential security risk as this opens access to the full power of CamelContext API.") 061 private boolean allowContextMapAll; 062 063 public ResourceEndpoint() { 064 } 065 066 public ResourceEndpoint(String endpointUri, Component component, String resourceUri) { 067 super(endpointUri, component); 068 this.resourceUri = resourceUri; 069 } 070 071 /** 072 * Gets the resource as an input stream considering the cache flag as well. 073 * <p/> 074 * If cache is enabled then the resource content is cached in an internal buffer and this content is 075 * returned to avoid loading the resource over and over again. 076 * 077 * @return the input stream 078 * @throws IOException is thrown if error loading the content of the resource to the local cache buffer 079 */ 080 public InputStream getResourceAsInputStream() throws IOException { 081 // try to get the resource input stream 082 InputStream is; 083 if (isContentCache()) { 084 synchronized (this) { 085 if (buffer == null) { 086 log.debug("Reading resource: {} into the content cache", resourceUri); 087 is = getResourceAsInputStreamWithoutCache(); 088 buffer = IOConverter.toBytes(is); 089 IOHelper.close(is, resourceUri, log); 090 } 091 } 092 log.debug("Using resource: {} from the content cache", resourceUri); 093 return new ByteArrayInputStream(buffer); 094 } 095 096 return getResourceAsInputStreamWithoutCache(); 097 } 098 099 protected InputStream getResourceAsInputStreamWithoutCache() throws IOException { 100 return loadResource(resourceUri); 101 } 102 103 /** 104 * Loads the given resource. 105 * 106 * @param uri uri of the resource. 107 * @return the loaded resource 108 * @throws IOException is thrown if resource is not found or cannot be loaded 109 */ 110 protected InputStream loadResource(String uri) throws IOException { 111 return ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), uri); 112 } 113 114 @ManagedAttribute(description = "Whether the resource is cached") 115 public boolean isContentCache() { 116 return contentCache; 117 } 118 119 @ManagedOperation(description = "Clears the cached resource, forcing to re-load the resource on next request") 120 public void clearContentCache() { 121 log.debug("Clearing resource: {} from the content cache", resourceUri); 122 buffer = null; 123 } 124 125 public boolean isContentCacheCleared() { 126 return buffer == null; 127 } 128 129 @ManagedAttribute(description = "Whether the context map is limited to only include the message body and headers") 130 public boolean isAllowContextMapAll() { 131 return allowContextMapAll; 132 } 133 134 /** 135 * Sets whether the context map should allow access to all details. 136 * By default only the message body and headers can be accessed. 137 * This option can be enabled for full access to the current Exchange and CamelContext. 138 * Doing so impose a potential security risk as this opens access to the full power of CamelContext API. 139 */ 140 public void setAllowContextMapAll(boolean allowContextMapAll) { 141 this.allowContextMapAll = allowContextMapAll; 142 } 143 144 @ManagedAttribute(description = "Camel context ID") 145 public String getCamelId() { 146 return getCamelContext().getName(); 147 } 148 149 @ManagedAttribute(description = "Camel ManagementName") 150 public String getCamelManagementName() { 151 return getCamelContext().getManagementName(); 152 } 153 154 @ManagedAttribute(description = "Endpoint service state") 155 public String getState() { 156 return getStatus().name(); 157 } 158 159 /** 160 * Sets whether to use resource content cache or not. 161 */ 162 public void setContentCache(boolean contentCache) { 163 this.contentCache = contentCache; 164 } 165 166 public String getResourceUri() { 167 return resourceUri; 168 } 169 170 /** 171 * Path to the resource. 172 * <p/> 173 * You can prefix with: classpath, file, http, ref, or bean. 174 * classpath, file and http loads the resource using these protocols (classpath is default). 175 * ref will lookup the resource in the registry. 176 * bean will call a method on a bean to be used as the resource. 177 * For bean you can specify the method name after dot, eg bean:myBean.myMethod 178 * 179 * @param resourceUri the resource path 180 */ 181 public void setResourceUri(String resourceUri) { 182 this.resourceUri = resourceUri; 183 } 184}