This commit is contained in:
Clebert Suconic 2017-05-24 18:44:37 -04:00
commit 9ff301dc38
2 changed files with 247 additions and 0 deletions

View File

@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.jndi;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
/**
* Converts objects implementing JNDIStorable into a property fields so they can be
* stored and regenerated from JNDI
*
* @since 1.0
*/
public class JNDIReferenceFactory implements ObjectFactory {
/**
* This will be called by a JNDIprovider when a Reference is retrieved from
* a JNDI store - and generates the original instance
*
* @param object
* the Reference object
* @param name
* the JNDI name
* @param nameCtx
* the context
* @param environment
* the environment settings used by JNDI
*
* @return the instance built from the Reference object
*
* @throws Exception
* if building the instance from Reference fails (usually class not found)
*/
@Override
public Object getObjectInstance(Object object, Name name, Context nameCtx, Hashtable<?, ?> environment)
throws Exception {
Object result = null;
if (object instanceof Reference) {
Reference reference = (Reference) object;
Class<?> theClass = loadClass(this, reference.getClassName());
if (JNDIStorable.class.isAssignableFrom(theClass)) {
JNDIStorable store = (JNDIStorable) theClass.newInstance();
Map<String, String> properties = new HashMap<>();
for (Enumeration<RefAddr> iter = reference.getAll(); iter.hasMoreElements();) {
StringRefAddr addr = (StringRefAddr) iter.nextElement();
properties.put(addr.getType(), (addr.getContent() == null) ? "" : addr.getContent().toString());
}
store.setProperties(properties);
result = store;
}
} else {
throw new RuntimeException("Object " + object + " is not a reference");
}
return result;
}
/**
* Create a Reference instance from a JNDIStorable object
*
* @param instanceClassName
* The name of the class that is being created.
* @param po
* The properties object to use when configuring the new instance.
*
* @return Reference
*
* @throws NamingException if an error occurs while creating the new instance.
*/
public static Reference createReference(String instanceClassName, JNDIStorable po) throws NamingException {
Reference result = new Reference(instanceClassName, JNDIReferenceFactory.class.getName(), null);
try {
Map<String, String> props = po.getProperties();
for (Map.Entry<String, String> entry : props.entrySet()) {
StringRefAddr addr = new StringRefAddr(entry.getKey(), entry.getValue());
result.add(addr);
}
} catch (Exception e) {
throw new NamingException(e.getMessage());
}
return result;
}
/**
* Retrieve the class loader for a named class
*
* @param thisObj
* Local object to use when doing the lookup.
* @param className
* The name of the class being loaded.
*
* @return the class that was requested.
*
* @throws ClassNotFoundException if a matching class cannot be created.
*/
public static Class<?> loadClass(Object thisObj, String className) throws ClassNotFoundException {
// try local ClassLoader first.
ClassLoader loader = thisObj.getClass().getClassLoader();
Class<?> theClass;
if (loader != null) {
theClass = loader.loadClass(className);
} else {
// Will be null in jdk1.1.8
// use default classLoader
theClass = Class.forName(className);
}
return theClass;
}
}

View File

@ -0,0 +1,116 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.jndi;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Facilitates objects to be stored in JNDI as properties
*
* @since 1.0
*/
public abstract class JNDIStorable implements Referenceable, Externalizable {
/**
* Set the properties that will represent the instance in JNDI
*
* @param props
* The properties to use when building the new isntance.
*
* @return a new, unmodifiable, map containing any unused properties, or empty if none were.
*/
protected abstract Map<String, String> buildFromProperties(Map<String, String> props);
/**
* Initialize the instance from properties stored in JNDI
*
* @param props
* The properties to use when initializing the new instance.
*/
protected abstract void populateProperties(Map<String, String> props);
/**
* set the properties for this instance as retrieved from JNDI
*
* @param props
* The properties to apply to this instance.
*
* @return a new, unmodifiable, map containing any unused properties, or empty if none were.
*/
public synchronized Map<String, String> setProperties(Map<String, String> props) {
return buildFromProperties(props);
}
/**
* Get the properties from this instance for storing in JNDI
*
* @return the properties
*/
public synchronized Map<String, String> getProperties() {
Map<String, String> properties = new LinkedHashMap<>();
populateProperties(properties);
return properties;
}
/**
* Retrieve a Reference for this instance to store in JNDI
*
* @return the built Reference
* @throws NamingException
* if error on building Reference
*/
@Override
public Reference getReference() throws NamingException {
return JNDIReferenceFactory.createReference(this.getClass().getName(), this);
}
/**
* @see Externalizable#readExternal(ObjectInput)
*/
@SuppressWarnings("unchecked")
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
Map<String, String> props = (Map<String, String>) in.readObject();
if (props != null) {
setProperties(props);
}
}
/**
* @see Externalizable#writeExternal(ObjectOutput)
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(getProperties());
}
protected String getProperty(Map<String, String> map, String key, String defaultValue) {
String value = map.get(key);
if (value != null) {
return value;
}
return defaultValue;
}
}