001/* 002 * (C) Copyright 2013-2018 Nuxeo (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.redis; 020 021import static java.nio.charset.StandardCharsets.UTF_8; 022import static org.nuxeo.runtime.model.Descriptor.UNIQUE_DESCRIPTOR_ID; 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027import java.util.Collections; 028 029import org.apache.commons.io.IOUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.apache.commons.text.StrBuilder; 032import org.nuxeo.runtime.api.Framework; 033import org.nuxeo.runtime.model.ComponentContext; 034import org.nuxeo.runtime.model.ComponentInstance; 035import org.nuxeo.runtime.model.DefaultComponent; 036import org.osgi.framework.Bundle; 037 038/** 039 * Implementation of the Redis Service holding the configured Jedis pool. 040 * 041 * @since 5.8 042 */ 043public class RedisComponent extends DefaultComponent implements RedisAdmin { 044 045 /** 046 * @since 10.3 047 */ 048 public static final String XP_CONFIG = "configuration"; 049 050 private static final String DEFAULT_PREFIX = "nuxeo:"; 051 052 protected volatile RedisExecutor executor; 053 054 protected String delsha; 055 056 @Override 057 public RedisPoolDescriptor getConfig() { 058 return getDescriptor(XP_CONFIG, UNIQUE_DESCRIPTOR_ID); 059 } 060 061 @Override 062 public void start(ComponentContext context) { 063 super.start(context); 064 RedisPoolDescriptor config = getConfig(); 065 if (config == null || config.disabled) { 066 return; 067 } 068 this.executor = config.newExecutor(); 069 try { 070 delsha = load("org.nuxeo.runtime.redis", "del-keys"); 071 } catch (RuntimeException cause) { 072 this.executor = null; 073 throw new RuntimeException("Cannot activate redis executor", cause); 074 } 075 } 076 077 @Override 078 public void stop(ComponentContext context) throws InterruptedException { 079 super.stop(context); 080 if (executor == null) { 081 return; 082 } 083 try { 084 executor.getPool().destroy(); 085 } finally { 086 executor = null; 087 } 088 } 089 090 @Override 091 public int getApplicationStartedOrder() { 092 ComponentInstance compo = Framework.getRuntime().getComponentInstance("org.nuxeo.ecm.core.work.service"); 093 return compo != null ? ((DefaultComponent) compo.getInstance()).getApplicationStartedOrder() - 1 : -500; 094 } 095 096 @Override 097 public Long clear(final String pattern) { 098 return (Long) executor.evalsha(delsha, Collections.singletonList(pattern), Collections.emptyList()); 099 } 100 101 @Override 102 public String load(String bundleName, String scriptName) { 103 Bundle b = Framework.getRuntime().getBundle(bundleName); 104 URL loc = b.getEntry(scriptName + ".lua"); 105 if (loc == null) { 106 throw new RuntimeException("Fail to load lua script: " + scriptName); 107 } 108 final StrBuilder builder; 109 try (InputStream is = loc.openStream()) { 110 builder = new StrBuilder(); 111 for (String line : IOUtils.readLines(is, UTF_8)) { 112 builder.appendln(line); 113 } 114 } catch (IOException e) { 115 throw new RuntimeException("Fail to load lua script: " + scriptName, e); 116 } 117 118 return executor.scriptLoad(builder.toString()); 119 } 120 121 @Override 122 public <T> T getAdapter(Class<T> adapter) { 123 if (adapter.isAssignableFrom(RedisExecutor.class)) { 124 return adapter.cast(executor); 125 } 126 return super.getAdapter(adapter); 127 } 128 129 @Override 130 public String namespace(String... names) { 131 RedisPoolDescriptor config = getConfig(); 132 String prefix = config == null ? null : config.prefix; 133 if (StringUtils.isBlank(prefix)) { 134 prefix = DEFAULT_PREFIX; 135 } 136 StringBuilder builder = new StringBuilder(prefix); 137 for (String name : names) { 138 builder.append(name).append(":"); 139 } 140 return builder.toString(); 141 } 142 143}