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